From 01c165cd1b2ac601d5ae73d3cb5e82ccdd94ac94 Mon Sep 17 00:00:00 2001 From: Le Chi Thu Date: Tue, 3 Apr 2012 01:23:00 +0200 Subject: Initial commit --- .config | 38 + .my_build_settings | 6 + Makefile | 88 + kernel/Makefile | 6 + kernel/kernel.mak | 49 + kernel/testcases/Makefile | 60 + kernel/testcases/dma/Makefile | 18 + kernel/testcases/dma/kernel_space/Makefile | 4 + kernel/testcases/dma/kernel_space/dma_test_lib.c | 477 ++++ kernel/testcases/dma/kernel_space/dma_test_lib.h | 105 + .../testcases/dma/kernel_space/dma_test_module.c | 2587 ++++++++++++++++++++ kernel/testcases/dma/user-space/Makefile | 26 + kernel/testcases/dma/user-space/dma.c | 156 ++ kernel/testcases/dma/user-space/dma_test_all.sh | 81 + ltp_framework/ChangeLog | 1 + ltp_framework/IDcheck.sh | 189 ++ ltp_framework/bin/ltp-pan | Bin 0 -> 61493 bytes ltp_framework/include/Makefile | 45 + ltp_framework/include/cleanup.c | 45 + ltp_framework/include/compiler.h | 18 + ltp_framework/include/config.h | 293 +++ ltp_framework/include/config.h.default | 251 ++ ltp_framework/include/config.h.in | 292 +++ ltp_framework/include/dataascii.h | 65 + ltp_framework/include/databin.h | 44 + ltp_framework/include/file_lock.h | 46 + ltp_framework/include/forker.h | 63 + ltp_framework/include/libtestsuite.h | 20 + ltp_framework/include/ltp_signal.h | 109 + ltp_framework/include/mk/automake.mk | 117 + ltp_framework/include/mk/config.mk | 82 + ltp_framework/include/mk/config.mk.default | 76 + ltp_framework/include/mk/config.mk.in | 82 + ltp_framework/include/mk/env_post.mk | 104 + ltp_framework/include/mk/env_pre.mk | 144 ++ ltp_framework/include/mk/features.mk | 55 + ltp_framework/include/mk/features.mk.default | 55 + ltp_framework/include/mk/features.mk.in | 55 + ltp_framework/include/mk/functions.mk | 76 + ltp_framework/include/mk/generic_leaf_target.inc | 106 + ltp_framework/include/mk/generic_leaf_target.mk | 24 + ltp_framework/include/mk/generic_trunk_target.inc | 97 + ltp_framework/include/mk/generic_trunk_target.mk | 24 + ltp_framework/include/mk/gitignore.mk | 51 + ltp_framework/include/mk/lib.mk | 64 + ltp_framework/include/mk/man.mk | 37 + ltp_framework/include/mk/testcases.mk | 55 + ltp_framework/include/open_flags.h | 73 + ltp_framework/include/pattern.h | 90 + ltp_framework/include/random_range.h | 45 + ltp_framework/include/rmobj.h | 12 + ltp_framework/include/safe_macros.h | 139 ++ ltp_framework/include/search_path.h | 36 + ltp_framework/include/stamp-h1 | 1 + ltp_framework/include/str_to_bytes.h | 39 + ltp_framework/include/string_to_tokens.h | 48 + ltp_framework/include/swaponoff.h | 18 + .../include/system_specific_hugepages_info.h | 30 + .../include/system_specific_process_info.h | 29 + ltp_framework/include/test.h | 253 ++ ltp_framework/include/tlibio.h | 161 ++ ltp_framework/include/usctest.h | 323 +++ ltp_framework/include/write_log.h | 170 ++ ltp_framework/lib/Makefile | 45 + ltp_framework/lib/cloner.c | 111 + ltp_framework/lib/dataascii.c | 217 ++ ltp_framework/lib/databin.c | 297 +++ ltp_framework/lib/datapid.c | 373 +++ ltp_framework/lib/file_lock.c | 208 ++ ltp_framework/lib/forker.c | 281 +++ ltp_framework/lib/get_high_address.c | 40 + ltp_framework/lib/get_path.c | 100 + ltp_framework/lib/libltp.a | Bin 0 -> 264326 bytes ltp_framework/lib/libtestsuite.c | 164 ++ ltp_framework/lib/ltp.pc | 10 + ltp_framework/lib/ltp.pc.in | 10 + ltp_framework/lib/mount_utils.c | 213 ++ ltp_framework/lib/open_flags.c | 330 +++ ltp_framework/lib/parse_opts.c | 879 +++++++ ltp_framework/lib/pattern.c | 168 ++ ltp_framework/lib/random_range.c | 917 +++++++ ltp_framework/lib/rmobj.c | 211 ++ ltp_framework/lib/safe_macros.c | 312 +++ ltp_framework/lib/search_path.c | 277 +++ ltp_framework/lib/self_exec.c | 218 ++ ltp_framework/lib/str_to_bytes.c | 210 ++ ltp_framework/lib/string_to_tokens.c | 109 + ltp_framework/lib/system_specific_hugepages_info.c | 93 + ltp_framework/lib/system_specific_process_info.c | 88 + ltp_framework/lib/tlibio.c | 2084 ++++++++++++++++ ltp_framework/lib/tst_cwd_has_free.c | 22 + ltp_framework/lib/tst_is_cwd.c | 52 + ltp_framework/lib/tst_kvercmp.c | 68 + ltp_framework/lib/tst_res.c | 812 ++++++ ltp_framework/lib/tst_sig.c | 271 ++ ltp_framework/lib/tst_tmpdir.c | 405 +++ ltp_framework/lib/write_log.c | 503 ++++ ltp_framework/runltp | 1005 ++++++++ ltp_framework/ver_linux | 89 + 99 files changed, 19145 insertions(+) create mode 100644 .config create mode 100644 .my_build_settings create mode 100644 Makefile create mode 100644 kernel/Makefile create mode 100644 kernel/kernel.mak create mode 100644 kernel/testcases/Makefile create mode 100644 kernel/testcases/dma/Makefile create mode 100644 kernel/testcases/dma/kernel_space/Makefile create mode 100644 kernel/testcases/dma/kernel_space/dma_test_lib.c create mode 100644 kernel/testcases/dma/kernel_space/dma_test_lib.h create mode 100644 kernel/testcases/dma/kernel_space/dma_test_module.c create mode 100644 kernel/testcases/dma/user-space/Makefile create mode 100644 kernel/testcases/dma/user-space/dma.c create mode 100755 kernel/testcases/dma/user-space/dma_test_all.sh create mode 100644 ltp_framework/ChangeLog create mode 100755 ltp_framework/IDcheck.sh create mode 100755 ltp_framework/bin/ltp-pan create mode 100644 ltp_framework/include/Makefile create mode 100644 ltp_framework/include/cleanup.c create mode 100644 ltp_framework/include/compiler.h create mode 100644 ltp_framework/include/config.h create mode 100644 ltp_framework/include/config.h.default create mode 100644 ltp_framework/include/config.h.in create mode 100644 ltp_framework/include/dataascii.h create mode 100644 ltp_framework/include/databin.h create mode 100644 ltp_framework/include/file_lock.h create mode 100644 ltp_framework/include/forker.h create mode 100644 ltp_framework/include/libtestsuite.h create mode 100644 ltp_framework/include/ltp_signal.h create mode 100644 ltp_framework/include/mk/automake.mk create mode 100644 ltp_framework/include/mk/config.mk create mode 100644 ltp_framework/include/mk/config.mk.default create mode 100644 ltp_framework/include/mk/config.mk.in create mode 100644 ltp_framework/include/mk/env_post.mk create mode 100644 ltp_framework/include/mk/env_pre.mk create mode 100644 ltp_framework/include/mk/features.mk create mode 100644 ltp_framework/include/mk/features.mk.default create mode 100644 ltp_framework/include/mk/features.mk.in create mode 100644 ltp_framework/include/mk/functions.mk create mode 100644 ltp_framework/include/mk/generic_leaf_target.inc create mode 100644 ltp_framework/include/mk/generic_leaf_target.mk create mode 100644 ltp_framework/include/mk/generic_trunk_target.inc create mode 100644 ltp_framework/include/mk/generic_trunk_target.mk create mode 100644 ltp_framework/include/mk/gitignore.mk create mode 100644 ltp_framework/include/mk/lib.mk create mode 100644 ltp_framework/include/mk/man.mk create mode 100644 ltp_framework/include/mk/testcases.mk create mode 100644 ltp_framework/include/open_flags.h create mode 100644 ltp_framework/include/pattern.h create mode 100644 ltp_framework/include/random_range.h create mode 100644 ltp_framework/include/rmobj.h create mode 100644 ltp_framework/include/safe_macros.h create mode 100644 ltp_framework/include/search_path.h create mode 100644 ltp_framework/include/stamp-h1 create mode 100644 ltp_framework/include/str_to_bytes.h create mode 100644 ltp_framework/include/string_to_tokens.h create mode 100644 ltp_framework/include/swaponoff.h create mode 100644 ltp_framework/include/system_specific_hugepages_info.h create mode 100644 ltp_framework/include/system_specific_process_info.h create mode 100644 ltp_framework/include/test.h create mode 100644 ltp_framework/include/tlibio.h create mode 100644 ltp_framework/include/usctest.h create mode 100644 ltp_framework/include/write_log.h create mode 100644 ltp_framework/lib/Makefile create mode 100644 ltp_framework/lib/cloner.c create mode 100644 ltp_framework/lib/dataascii.c create mode 100644 ltp_framework/lib/databin.c create mode 100644 ltp_framework/lib/datapid.c create mode 100644 ltp_framework/lib/file_lock.c create mode 100644 ltp_framework/lib/forker.c create mode 100644 ltp_framework/lib/get_high_address.c create mode 100644 ltp_framework/lib/get_path.c create mode 100644 ltp_framework/lib/libltp.a create mode 100644 ltp_framework/lib/libtestsuite.c create mode 100644 ltp_framework/lib/ltp.pc create mode 100644 ltp_framework/lib/ltp.pc.in create mode 100644 ltp_framework/lib/mount_utils.c create mode 100644 ltp_framework/lib/open_flags.c create mode 100644 ltp_framework/lib/parse_opts.c create mode 100644 ltp_framework/lib/pattern.c create mode 100644 ltp_framework/lib/random_range.c create mode 100644 ltp_framework/lib/rmobj.c create mode 100644 ltp_framework/lib/safe_macros.c create mode 100644 ltp_framework/lib/search_path.c create mode 100644 ltp_framework/lib/self_exec.c create mode 100644 ltp_framework/lib/str_to_bytes.c create mode 100644 ltp_framework/lib/string_to_tokens.c create mode 100644 ltp_framework/lib/system_specific_hugepages_info.c create mode 100644 ltp_framework/lib/system_specific_process_info.c create mode 100644 ltp_framework/lib/tlibio.c create mode 100644 ltp_framework/lib/tst_cwd_has_free.c create mode 100644 ltp_framework/lib/tst_is_cwd.c create mode 100644 ltp_framework/lib/tst_kvercmp.c create mode 100644 ltp_framework/lib/tst_res.c create mode 100644 ltp_framework/lib/tst_sig.c create mode 100644 ltp_framework/lib/tst_tmpdir.c create mode 100644 ltp_framework/lib/write_log.c create mode 100755 ltp_framework/runltp create mode 100755 ltp_framework/ver_linux diff --git a/.config b/.config new file mode 100644 index 0000000..ffce626 --- /dev/null +++ b/.config @@ -0,0 +1,38 @@ +# +# Automatically generated make config: don't edit +# Wed Mar 28 23:45:55 2012 +# +#CONFIG_LTP=y +CONFIG_LTP_STE_TESTCASES=y +# CONFIG_LTP_ALSA_I2C is not set +# CONFIG_LTP_SENSORS_AB8500 is not set +CONFIG_LTP_DMA=y +# CONFIG_LTP_METATEST is not set +# CONFIG_LTP_EXAMPLE is not set +# CONFIG_LTP_RTC is not set +# CONFIG_LTP_BLUETOOTH is not set +# CONFIG_LTP_GPIO is not set +# CONFIG_LTP_MCDE is not set +# CONFIG_LTP_B2R2 is not set +# CONFIG_LTP_UART is not set +# CONFIG_LTP_SSP is not set +# CONFIG_LTP_SHRM is not set +# CONFIG_LTP_I2C is not set +# CONFIG_LTP_DLP is not set +# CONFIG_LTP_MMC is not set +# CONFIG_LTP_EMMC_FILESYSTEM_MMC_VALIDATION_LTP is not set +# CONFIG_LTP_MSP is not set +# CONFIG_LTP_ALS is not set +# CONFIG_LTP_LSM303DLH is not set +# CONFIG_LTP_LPS001WP is not set +# CONFIG_LTP_L3G4200D is not set +# CONFIG_LTP_PROXIMITY is not set +# CONFIG_LTP_POWER is not set +# CONFIG_LTP_TEE is not set +# CONFIG_LTP_TIMER is not set +# CONFIG_LTP_HSI is not set +# CONFIG_LTP_LED is not set +# CONFIG_LTP_VIBRATOR is not set +# CONFIG_LTP_L2CACHE is not set +# CONFIG_LTP_STE_SYSTEMTEST_TESTCASES is not set +# CONFIG_LTP_COMMUNITY_TESTCASES is not set diff --git a/.my_build_settings b/.my_build_settings new file mode 100644 index 0000000..0ff1a12 --- /dev/null +++ b/.my_build_settings @@ -0,0 +1,6 @@ +#ARCH=arm +#CROSS_PREFIX=arm-linux-gnueabi +#CROSS_COMPILE=arm-linux-gnueabi- +#KERNEL_OUTPUT=/home/kalle/projects/snowball/kernel +#DESTDIR=/home/kalle/projects/snowball/my_install + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..96bbb9b --- /dev/null +++ b/Makefile @@ -0,0 +1,88 @@ +# Standalone build file for LTP + +# Edit .my_build_settings to set proper values for these variables +# ARCH /* arm */ +# CROSS_PREFIX /* arm-none-linux-gnueabi */ +# CROSS_COMPILE /* arm-none-linux-gnueabi- */ +# KERNEL_OUTPUT /* kernel build directory */ +# DESTDIR /* installation output directory */ +-include .my_build_settings +ARCH ?= arm +KERNEL_OUTPUT ?= /lib/modules/$(shell uname -r)/build +DESTDIR ?= $(CURDIR)/../ste_test_install_dir + +# Default config file +LTP_CONFIG ?= defconfig +# Number of parallell make jobs +JOBS ?= 1 +# ------------ + +# TODO: remove this export and pass command line variables to make instead. +# Setting CC is required in order to build userspace parts of kernel tests. +export CC=$(CROSS_COMPILE)gcc +# -------------------- + +# The following variables should have ok default values +# ---------------- + +# tempdir can't be changed easily because it is hardcoded in the Makefiles +TEMPDIR := $(CURDIR)/tempdir + +# Local script directory +SCRIPT_DIR := $(CURDIR)/scripts +BUILD_PREFIX := i386-pc-linux-gnu +HOST_PREFIX := $(CROSS_PREFIX) +TARGET_PREFIX := $(CROSS_PREFIX) +# ---------------- + +# Pass variables to make +MAKEFLAGS := +MAKEFLAGS += CROSS_COMPILE=$(CROSS_COMPILE) +MAKEFLAGS += CROSS_PREFIX=$(CROSS_PREFIX) +MAKEFLAGS += ARCH=$(ARCH) +MAKEFLAGS += KERNEL_OUTPUT=$(KERNEL_OUTPUT) +MAKEFLAGS += KERNELDIR=$(KERNEL_OUTPUT) +MAKEFLAGS += DESTDIR=$(DESTDIR) +MAKEFLAGS += TEMPDIR=$(TEMPDIR) +MAKEFLAGS += HOST_PREFIX=$(HOST_PREFIX) +MAKEFLAGS += TARGET_PREFIX=$(TARGET_PREFIX) +MAKEFLAGS += CONFIG_LTP_STE_TESTCASES=$(CONFIG_LTP_STE_TESTCASES) +MAKEFLAGS += JOBS=$(JOBS) +MAKEFLAGS += SCRIPT_DIR=$(SCRIPT_DIR) + +# TODO: Replace this export and pass value via make +export LTP_TEST_CONFIG_FILE=$(CURDIR)/.config +.PHONY help: +help: FORCE + @echo "Please read the Makefile for a list of make targets." + @echo "Overview of build flow:" + @echo "1. make menuconfig OR make config (set default configuration." + @echo " Check the defaults to make sure this is what you want" + @echo "2. make tests (builds the out of tree tests according to the config from step #1" + @echo "3. make install (installs the out of tree tests built in step #3" + @echo "4. make clean (remove build content, doesn't uninstall content from step #4" + +menuconfig: FORCE + $(MAKE) -r --directory=$(CURDIR)/kconfig mconf + $(CURDIR)/kconfig/mconf $(CURDIR)/config/Kconfig + +.PHONY config: +config: FORCE + cp config/$(LTP_CONFIG) .config + +# Build the out of tree tests +.PHONY tests: +tests: FORCE + $(MAKE) --directory=kernel -f kernel.mak $(MAKEFLAGS) build + +# Install the out of tree tests +.PHONY install: +install: FORCE + $(MAKE) --directory=kernel -f kernel.mak $(MAKEFLAGS) install + cp -r $(CURDIR)/ltp_framework/* $(DESTDIR)/opt/ltp + +.PHONY: clean +clean: + $(MAKE) --directory=kernel -f kernel.mak $(MAKEFLAGS) clean + +FORCE: diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000..0cbe200 --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,6 @@ +-include $(abspath $(TOPLEVEL)/../../ltp/.config) +ifeq ($(realpath $(TOPLEVEL)/../../ltp/.config),) +include $(LTP_TEST_CONFIG_FILE) +endif + +obj-$(CONFIG_LTP_STE_TESTCASES) += testcases/ diff --git a/kernel/kernel.mak b/kernel/kernel.mak new file mode 100644 index 0000000..840da0b --- /dev/null +++ b/kernel/kernel.mak @@ -0,0 +1,49 @@ +# Compile this package with small thumb code - +# not all packages work with this, then you have to comment +# this out or patch the package. +ifdef USE_THUMB + CFLAGS := -mthumb -mthumb-interwork $(CFLAGS) +endif + +BUILD_ROOT := testcases +KERNELDIR ?= ../../kernel + +.PHONY: build +build: build-modules build-userspace + +.PHONY: build-modules +build-modules: kernel.mak + echo "$@" + $(MAKE) --directory=$(KERNEL_OUTPUT) M=$(shell pwd) -j$(JOBS) modules + +.PHONY: build-userspace +build-userspace: kernel.mak + echo "$@" + $(MAKE) --directory=$(BUILD_ROOT) -j$(JOBS) all + + +.PHONY: install +install: install-modules install-userspace + +.PHONY: install-modules +install-modules: build-modules + echo "$@" +ifneq ($(CROSS_COMPILE),) + $(MAKE) --directory=$(KERNEL_OUTPUT) M=$(shell pwd) -j$(JOBS) modules_install +else + $(MAKE) --directory=$(KERNEL_OUTPUT) M=$(shell pwd) INSTALL_MOD_PATH=$(DESTDIR) -j$(JOBS) modules_install +endif + depmod + +.PHONY: install-userspace +install-userspace: build-userspace + echo "$@" + cd $(BUILD_ROOT) && $(MAKE) install DESTDIR=$(DESTDIR) + $(shell install -d $(DESTDIR)/opt/ltp/runtest) + cp -f runtest/* $(DESTDIR)/opt/ltp/runtest + +.PHONY: clean +clean: + $(MAKE) --directory=$(BUILD_ROOT) clean + $(MAKE) --directory=$(KERNELDIR) M=$(shell pwd) clean + find . -name 'modules.order' -delete diff --git a/kernel/testcases/Makefile b/kernel/testcases/Makefile new file mode 100644 index 0000000..72931da --- /dev/null +++ b/kernel/testcases/Makefile @@ -0,0 +1,60 @@ +# Disabled test | Reason +# -------------------|-------------------------------------------------------- +# pwrmgmt | Specific hw/sw requirements + + +-include $(abspath $(TOPLEVEL)/../../ltp/.config) +# If TOPLEVEL path doesn't exist test local path +ifeq ($(realpath $(TOPLEVEL)/../../ltp/.config),) +include $(LTP_TEST_CONFIG_FILE) +endif + +#obj-$(CONFIG_LTP_ALSA_I2C) += alsa_i2c/ +#obj-$(CONFIG_LTP_SENSORS_AB8500) += sensors_ab8500/ +#obj-$(CONFIG_LTP_METATEST) += metatest/ +#obj-$(CONFIG_LTP_EXAMPLE) += example/ +obj-$(CONFIG_LTP_DMA) += dma/ +#obj-$(CONFIG_LTP_RTC) += rtc/ +#obj-$(CONFIG_LTP_BLUETOOTH) += ste_conn/ +#obj-$(CONFIG_LTP_GPIO) += gpio/ +#obj-$(CONFIG_LTP_MCDE) += mcde/ +#obj-$(CONFIG_LTP_B2R2) += b2r2/ +#obj-$(CONFIG_LTP_UART) += uart/ +#obj-$(CONFIG_LTP_SSP) += ssp/ +#obj-$(CONFIG_LTP_SHRM) += shrm/ +#obj-$(CONFIG_LTP_I2C) += i2c/ +#obj-$(CONFIG_LTP_DLP) += dlp/ +#obj-$(CONFIG_LTP_MMC) += mmc/ +#obj-$(CONFIG_LTP_EMMC_FILESYSTEM_MMC_VALIDATION_LTP) += emmc_filesystem_mmc_Validation_LTP/ +#obj-$(CONFIG_LTP_MSP) += msp/ +#obj-$(CONFIG_LTP_ALS) += als/ +#obj-$(CONFIG_LTP_LSM303DLH) += lsm303dlh/ +#obj-$(CONFIG_LTP_LPS001WP) += lps001wp_prs/ +#obj-$(CONFIG_LTP_L3G4200D) += l3g4200d/ +#obj-$(CONFIG_LTP_PROXIMITY) += proximity/ +#obj-$(CONFIG_LTP_PWRMGMT) += pwrmgmt/ +#obj-$(CONFIG_LTP_TEE) += tee/ +#obj-$(CONFIG_LTP_HIGHRES_TIMER) += highres_timer/ +#obj-$(CONFIG_LTP_TIMER) += timer/ +#obj-$(CONFIG_LTP_HSI) += hsi_test/ +#obj-$(CONFIG_LTP_LED) += led/ +#obj-$(CONFIG_LTP_VIBRATOR) += vibrator/ +#obj-$(CONFIG_LTP_L2CACHE) += l2cache/ + +ifneq ($(KERNELRELEASE),) + +# kernel modules should be built by descending here like this: +# obj-y := dir1/ dir2/ + +else + +all: + @set -e; for i in $(obj-y); do $(MAKE) -C $$i ; done + +install: + @set -e; for i in $(obj-y); do $(MAKE) -C $$i install ; done + +clean: + @set -e; for i in $(obj-y) ; do $(MAKE) -C $$i clean ; done + +endif diff --git a/kernel/testcases/dma/Makefile b/kernel/testcases/dma/Makefile new file mode 100644 index 0000000..c49641a --- /dev/null +++ b/kernel/testcases/dma/Makefile @@ -0,0 +1,18 @@ +ifneq ($(KERNELRELEASE),) + +obj-y := kernel_space/ + +else + +SUBDIRS := user-space + +all: + @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i ; done + +install: + @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i install ; done + +clean: + @set -e; for i in $(SUBDIRS) ; do $(MAKE) -C $$i clean ; done + +endif diff --git a/kernel/testcases/dma/kernel_space/Makefile b/kernel/testcases/dma/kernel_space/Makefile new file mode 100644 index 0000000..e973fee --- /dev/null +++ b/kernel/testcases/dma/kernel_space/Makefile @@ -0,0 +1,4 @@ +EXTRA_CFLAGS := -I$(abspath $(M)/framework/include-kernel) + +obj-m := stedma40_test.o +stedma40_test-objs := dma_test_lib.o dma_test_module.o diff --git a/kernel/testcases/dma/kernel_space/dma_test_lib.c b/kernel/testcases/dma/kernel_space/dma_test_lib.c new file mode 100644 index 0000000..7d77537 --- /dev/null +++ b/kernel/testcases/dma/kernel_space/dma_test_lib.c @@ -0,0 +1,477 @@ +/* + * Copyright (C) ST-Ericsson SA 2007-2010 + * Author: Per Friden for ST-Ericsson + * Author: Jonas Aaberg for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dma_test_lib.h" + +#ifdef CONFIG_STE_DMA40_DEBUG +extern void sted40_history_dump(void); +#else +static void sted40_history_dump(void) +{ +} + +#endif + +MODULE_DESCRIPTION("DMA test lib: Support functions for DMA testing"); +MODULE_LICENSE("GPL"); + +/* To get various debug prints put an x after this macro */ +#define DBG_PRINT(x) +#define DBG_FAULT_PRINT(x) x + + +static void transfer_timedout(struct work_struct *work) +{ + int i; + struct buflist *buflist; + + buflist = container_of(work, struct buflist, timed_out.work); + + DBG_FAULT_PRINT(printk(KERN_ERR "dma_test_lib: ERROR - DMA transfer timed out!\n")); + DBG_FAULT_PRINT(printk(KERN_ERR "Testcase: %s failed\n", + buflist->name)); + + + for (i = 0; buflist->list_size[i] != -1; i++) { + printk(KERN_INFO "%p Transfer %d bytes from phy %x to %x\n", + buflist, + buflist->list_size[i], + buflist->list_src_phy[i], + buflist->list_dst_phy[i]); + } + printk(KERN_INFO "%p %d jobs\n", buflist, i); + + sted40_history_dump(); + +} + +static void transmit_cb(void *data) +{ + struct buflist *buflist = data; + unsigned long flags; + + DBG_PRINT(printk + (KERN_INFO "[%s] finished_jobs %d\n", __func__, + buflist->finished_jobs)); + + cancel_delayed_work(&buflist->timed_out); + + spin_lock_irqsave(&buflist->lock, flags); + buflist->finished_jobs++; + spin_unlock_irqrestore(&buflist->lock, flags); + + if (buflist->callback) + buflist->callback(buflist); +} + +int dmatest_buflist_create(struct buflist *buflist, int length, + int end_padding, + char *name, unsigned long dma_engine_flags, + int timeout, bool request_phy_chan, + struct dma_chan *dma_chan) +{ + dma_cap_mask_t mask; + + DBG_PRINT(printk(KERN_INFO "[%s]\n", __func__)); + buflist->is_dma_prepared = false; + buflist->dma_engine_flags = dma_engine_flags; + + dma_cap_zero(mask); + dma_cap_set(DMA_MEMCPY, mask); + if (request_phy_chan) + dma_cap_set(DMA_SLAVE, mask); + + if (dma_chan) + buflist->dma_chan = dma_chan; + else + buflist->dma_chan = dma_request_channel(mask, NULL, NULL); + + if (buflist->dma_chan == NULL) { + DBG_PRINT(printk(KERN_ERR "[%s] dma_request_channel failed\n", + __func__)); + return -EINVAL; + } + + spin_lock_init(&buflist->lock); + + buflist->list_len = length; + buflist->finished_jobs = 0; + strncpy(buflist->name, name, MAX_NAME_LEN-1); + + buflist->sent_jobs = 0; + + buflist->list_size = + kmalloc(sizeof(buflist->list_size) * length + 1, GFP_KERNEL); + buflist->list_buf_dst = + kmalloc(sizeof(buflist->list_buf_dst) * length, GFP_KERNEL); + buflist->list_buf_dst_real = + kmalloc(sizeof(buflist->list_buf_dst_real) * length, + GFP_KERNEL); + buflist->list_buf_src = + kmalloc(sizeof(buflist->list_buf_src) * length, GFP_KERNEL); + buflist->desc = + kmalloc(sizeof(struct dma_async_tx_descriptor *) * length, + GFP_KERNEL); + buflist->cookie = + kmalloc(sizeof(dma_cookie_t) * length, + GFP_KERNEL); + buflist->list_dst_phy = kmalloc(sizeof(dma_addr_t) * length, + GFP_KERNEL); + buflist->list_src_phy = kmalloc(sizeof(dma_addr_t) * length, + GFP_KERNEL); + buflist->sgl_src = + kmalloc(sizeof(struct scatterlist) * length, GFP_KERNEL); + buflist->sgl_dst = + kmalloc(sizeof(struct scatterlist) * length, GFP_KERNEL); + + sg_init_table(buflist->sgl_src, length); + sg_init_table(buflist->sgl_dst, length); + + buflist->end_padding = end_padding; + buflist->timeout_len = timeout; + buflist->callback = NULL; + + INIT_DELAYED_WORK_DEFERRABLE(&buflist->timed_out, transfer_timedout); + + return 0; +} + +void dmatest_buflist_destroy(struct buflist *buflist) +{ + DBG_PRINT(printk(KERN_INFO "[%s]\n", __func__)); + + if (buflist->dma_chan) + dma_release_channel(buflist->dma_chan); + + dmatest_buflist_free(buflist); + + kfree(buflist->list_size); + kfree(buflist->list_buf_dst); + kfree(buflist->list_buf_dst_real); + kfree(buflist->list_buf_src); + kfree(buflist->desc); + kfree(buflist->cookie); + kfree(buflist->list_dst_phy); + kfree(buflist->list_src_phy); + kfree(buflist->sgl_src); + kfree(buflist->sgl_dst); + + buflist->list_size = NULL; + buflist->list_buf_dst = NULL; + buflist->list_buf_dst_real = NULL; + buflist->list_buf_src = NULL; + buflist->desc = NULL; + buflist->cookie = NULL; + buflist->list_dst_phy = NULL; + buflist->list_src_phy = NULL; + buflist->sgl_src = NULL; + buflist->sgl_dst = NULL; +} + +void dmatest_sizelist_randomize(struct buflist *buflist, u32 min, u32 max, int align) +{ + int i; + struct timespec ts = current_kernel_time(); + + DBG_PRINT(printk(KERN_INFO "[%s]\n", __func__)); + + srandom32(ts.tv_nsec); + + for (i = 0; i < buflist->list_len; i++) { + buflist->list_size[i] = + ALIGN(random32() / (0xFFFFFFFF / (max - min)) + min, align); +/* DBG_PRINT(printk(KERN_INFO "rand value %d , min %d max %d\n", */ +/* buflist->list_size[i], min, max)); */ + + /* TODO replace BUG_ON:s with error report, return -1 */ + BUG_ON(buflist->list_size[i] > ALIGN(max, align)); + } + + buflist->list_size[i] = -1; +} + +void dmatest_sizelist_set(struct buflist *buflist, u32 value, int align) +{ + int i; + + DBG_PRINT(printk(KERN_INFO "[%s]\n", __func__)); + + for (i = 0; i < buflist->list_len; i++) { + buflist->list_size[i] = ALIGN(value, align); + } + + buflist->list_size[i] = -1; +} + +void dmatest_buflist_alloc(struct buflist *buflist) +{ + int i; + int buf_i; + int size; + + DBG_PRINT(printk(KERN_INFO "[%s]\n", __func__)); + + for (buf_i = 0; buflist->list_size[buf_i] != -1; buf_i++) { + size = buflist->list_size[buf_i]; + buflist->list_buf_dst_real[buf_i] = + kmalloc(size + buflist->end_padding + 2 * dma_get_cache_alignment(), + GFP_KERNEL); + buflist->list_buf_dst[buf_i] = PTR_ALIGN(buflist->list_buf_dst_real[buf_i], + dma_get_cache_alignment()); + buflist->list_buf_src[buf_i] = + kmalloc(size + buflist->end_padding, GFP_KERNEL); + + for (i = 0; i < size; i++) { + buflist->list_buf_src[buf_i][i] = (u8) (i + buf_i); + buflist->list_buf_dst[buf_i][i] = 0xAA; + } + for (i = size; i < size + buflist->end_padding; i++) { + buflist->list_buf_src[buf_i][i] = 0xBE; + buflist->list_buf_dst[buf_i][i] = 0xBE; + } + if (buflist->end_padding) { + dma_map_single(buflist->dma_chan->device->dev, + &buflist->list_buf_dst[buf_i][size], + buflist->end_padding, + DMA_BIDIRECTIONAL); + dma_map_single(buflist->dma_chan->device->dev, + &buflist->list_buf_src[buf_i][size], + buflist->end_padding, + DMA_BIDIRECTIONAL); + } + } + + for (i = 0; buflist->list_size[i] != -1; i++) { + sg_set_buf(&buflist->sgl_src[i], + buflist->list_buf_src[i], + buflist->list_size[i]); + sg_set_buf(&buflist->sgl_dst[i], + buflist->list_buf_dst[i], + buflist->list_size[i]); + } + +} + +void dmatest_buflist_free(struct buflist *buflist) +{ + int i; + + DBG_PRINT(printk(KERN_INFO "[%s]\n", __func__)); + + for (i = 0; buflist->list_size[i] != -1; i++) { + kfree(buflist->list_buf_dst_real[i]); + kfree(buflist->list_buf_src[i]); + + buflist->list_buf_dst[i] = 0; + buflist->list_buf_src[i] = 0; + } + +} + +int dmatest_buflist_payload_check(struct buflist *buflist) +{ + int err = 0; + int i; + + DBG_PRINT(printk(KERN_INFO "[%s]\n", __func__)); + + if (buflist->sgl_src_len) + dma_unmap_sg(buflist->dma_chan->device->dev, + buflist->sgl_src, buflist->sgl_src_len, + DMA_BIDIRECTIONAL); + + if (buflist->sgl_dst_len) + dma_unmap_sg(buflist->dma_chan->device->dev, + buflist->sgl_dst, buflist->sgl_dst_len, + DMA_BIDIRECTIONAL); + + for (i = 0; buflist->list_size[i] != -1; i++) { + if (!buflist->sgl_src_len) + dma_unmap_single(buflist->dma_chan->device->dev, + buflist->list_src_phy[i], + buflist->list_size[i], DMA_BIDIRECTIONAL); + + if (!buflist->sgl_dst_len) + dma_unmap_single(buflist->dma_chan->device->dev, + buflist->list_dst_phy[i], + buflist->list_size[i], DMA_BIDIRECTIONAL); + + if (memcmp + (buflist->list_buf_dst[i], buflist->list_buf_src[i], + buflist->list_size[i]) != 0) { + + DBG_FAULT_PRINT(printk + (KERN_INFO "[%s] fault index %d\n", + __func__, i)); + + dmatest_buflist_payload_printdiff(buflist, i); + err = -1; + } + } + + if (err) { + DBG_FAULT_PRINT(printk(KERN_INFO "Testcase: %s failed\n", buflist->name)); + sted40_history_dump(); + } + + return err; +} + +#define MAX_ERROR_PRINTS 16 +void dmatest_buflist_payload_printdiff(struct buflist *buflist, + u32 buf_index) +{ + int i, el = 0; + int size = buflist->list_size[buf_index]; + u8 *buf_dst = buflist->list_buf_dst[buf_index]; + u8 *buf_src = buflist->list_buf_src[buf_index]; + + DBG_FAULT_PRINT(printk + (KERN_INFO "[%s] fault buffer index %d dst at phy: 0x%lx\n", + __func__, buf_index, virt_to_phys(buf_dst))); + + for (i = 0; i < size; i++) { + if (buf_dst[i] != buf_src[i]) { + DBG_FAULT_PRINT(printk + (KERN_INFO + "Buffer fault index %d: " + "DEST data 0x%x Virt addr %p, phy 0x%x, SRC data: 0x%x\n", + i, buf_dst[i], + buflist->list_buf_dst[buf_index] + i, + buflist->list_dst_phy[buf_index] + i, + buf_src[i])); + el++; + if (el == MAX_ERROR_PRINTS) + break; + } + } +} + +void dmatest_buflist_start_single(struct buflist *buflist, + void (*callback)(struct buflist *bf)) +{ + int i; + + DBG_PRINT(printk(KERN_INFO "[%s]\n", __func__)); + + if ((buflist->dma_engine_flags & DMA_CTRL_ACK) || + !buflist->is_dma_prepared) { + for (i = 0; buflist->list_size[i] != -1; i++) { + + buflist->list_src_phy[i] = + dma_map_single(buflist->dma_chan->device->dev, + buflist->list_buf_src[i], + buflist->list_size[i], + DMA_BIDIRECTIONAL); + + buflist->list_dst_phy[i] = + dma_map_single(buflist->dma_chan->device->dev, + buflist->list_buf_dst[i], + buflist->list_size[i], + DMA_BIDIRECTIONAL); + + buflist->desc[i] = buflist->dma_chan->device-> + device_prep_dma_memcpy(buflist->dma_chan, + buflist->list_dst_phy[i], + buflist->list_src_phy[i], + buflist->list_size[i], + buflist->dma_engine_flags); + + buflist->desc[i]->callback = transmit_cb; + buflist->desc[i]->callback_param = buflist; + } + buflist->is_dma_prepared = true; + } + buflist->callback = callback; + + buflist->sgl_src_len = 0; + buflist->sgl_dst_len = 0; + + for (i = 0; buflist->list_size[i] != -1; i++) { + buflist->cookie[i] = buflist->desc[i]->tx_submit(buflist->desc[i]); + } + schedule_delayed_work(&buflist->timed_out, + msecs_to_jiffies(buflist->timeout_len)); + + dma_async_issue_pending(buflist->dma_chan); +} + +void dmatest_buflist_start_sg(struct buflist *buflist, + void (*callback)(struct buflist *bf)) +{ + DBG_PRINT(printk(KERN_INFO "[%s]\n", __func__)); + + buflist->sgl_src_len = dma_map_sg(buflist->dma_chan->device->dev, + buflist->sgl_src, buflist->list_len, + DMA_BIDIRECTIONAL); + buflist->sgl_dst_len = dma_map_sg(buflist->dma_chan->device->dev, + buflist->sgl_dst, buflist->list_len, + /* Both direction for verifying transfered data */ + DMA_BIDIRECTIONAL); + + if ((buflist->dma_engine_flags & DMA_CTRL_ACK) || + !buflist->is_dma_prepared) { + buflist->desc[0] = buflist->dma_chan->device->device_prep_dma_sg(buflist->dma_chan, + buflist->sgl_dst, + buflist->sgl_dst_len, + buflist->sgl_src, + buflist->sgl_src_len, + buflist->dma_engine_flags); + + buflist->desc[0]->callback = transmit_cb; + buflist->desc[0]->callback_param = buflist; + buflist->is_dma_prepared = true; + } + + buflist->callback = callback; + + buflist->cookie[0] = buflist->desc[0]->tx_submit(buflist->desc[0]); + schedule_delayed_work(&buflist->timed_out, + msecs_to_jiffies(buflist->timeout_len)); + + dma_async_issue_pending(buflist->dma_chan); + +} + +void dmatest_buflist_reset_nbr_finished(struct buflist *buflist) +{ + unsigned long flags; + + spin_lock_irqsave(&buflist->lock, flags); + + buflist->finished_jobs = 0; + buflist->sent_jobs = 0; + spin_unlock_irqrestore(&buflist->lock, flags); +} + +int dmatest_buflist_get_nbr_finished(struct buflist *buflist) +{ + unsigned long flags; + u32 ret; + + spin_lock_irqsave(&buflist->lock, flags); + ret = buflist->finished_jobs; + spin_unlock_irqrestore(&buflist->lock, flags); + + return ret; +} + diff --git a/kernel/testcases/dma/kernel_space/dma_test_lib.h b/kernel/testcases/dma/kernel_space/dma_test_lib.h new file mode 100644 index 0000000..fed1a3d --- /dev/null +++ b/kernel/testcases/dma/kernel_space/dma_test_lib.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) ST-Ericsson SA 2007-2010 + * Author: Per Friden for ST-Ericsson + * Author: Jonas Aaberg for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_NAME_LEN 128 + +struct buflist { + spinlock_t lock; + + struct dma_async_tx_descriptor **desc; + char name[MAX_NAME_LEN]; + int *list_size; + dma_addr_t *list_dst_phy; + dma_addr_t *list_src_phy; + u8 **list_buf_dst; + u8 **list_buf_dst_real; + u8 **list_buf_src; + struct scatterlist *sgl_dst; + struct scatterlist *sgl_src; + unsigned int sgl_dst_len; + unsigned int sgl_src_len; + + unsigned long dma_engine_flags; + bool is_dma_prepared; + u32 list_len; + + struct dma_chan *dma_chan; + dma_cookie_t *cookie; + + void (*callback)(struct buflist *bf); + struct workqueue_struct *wq; + u32 finished_jobs; + u32 sent_jobs; + + struct delayed_work timed_out; + int timeout_len; + u32 end_padding; +}; + +/* Initiate dma test + * + * returns 0 on success otherwise none zero + */ +int dmatest_init(void); + + +/** Creates a buffer list + * @length specifies length of buffer and size list + * + */ +int dmatest_buflist_create(struct buflist *buflist, int length, + int end_padding, + char *name, unsigned long dma_engine_flags, + int timeout, bool request_phy_chan, struct dma_chan *dma_chan); + +/* Destroys a buffer list, calls dmatest_buflist_free if list is != NULL */ +void dmatest_buflist_destroy(struct buflist *buflist); + +/* Allocates buffers according to size list and writes a pattern to the buffer, + * dmatest_sizelist_randomize or dmatest_sizelist_set must be + * called before this function + */ +void dmatest_buflist_alloc(struct buflist *buflist); + +/* Frees the buffers allocate by dmatest_buflist_alloc */ +void dmatest_buflist_free(struct buflist *buflist); + +/* Initialize size list with random values between min and max */ +void dmatest_sizelist_randomize(struct buflist *buflist, u32 min, u32 max, int align); + +/* Initialize size list with value */ +void dmatest_sizelist_set(struct buflist *buflist, u32 value, int align); + +/* Start sending the buflist to DMA as many single jobs, calls callback when done */ +void dmatest_buflist_start_single(struct buflist *buflist, + void (*callback)(struct buflist *bf)); + +/* Start sending the buflist to DMA as a scatter-gatter list, calls callback when done */ +void dmatest_buflist_start_sg(struct buflist *buflist, + void (*callback)(struct buflist *bf)); + +/* Verify the buffer according to the pattern written by dmatest_buflist_alloc. + * Returns 0 if ok otherwise -(index +1) + */ +int dmatest_buflist_payload_check(struct buflist *buflist); + +/* prints the difference between TX and RX for buffer number buf_index */ +void dmatest_buflist_payload_printdiff(struct buflist *buflist, + u32 buf_index); + +void dmatest_buflist_reset_nbr_finished(struct buflist *buflist); + +int dmatest_buflist_get_nbr_finished(struct buflist *buflist); diff --git a/kernel/testcases/dma/kernel_space/dma_test_module.c b/kernel/testcases/dma/kernel_space/dma_test_module.c new file mode 100644 index 0000000..6dae62b --- /dev/null +++ b/kernel/testcases/dma/kernel_space/dma_test_module.c @@ -0,0 +1,2587 @@ +/* + * Copyright (C) ST-Ericsson SA 2007-2010 + * Author: Per Friden for ST-Ericsson + * Author: Jonas Aaberg for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dma_test_lib.h" + +#ifndef CONFIG_DEBUG_FS +#error "DEBUG_FS must be set" +#endif + + +MODULE_DESCRIPTION("DMA test module: Test case for DMA"); +MODULE_LICENSE("GPL"); + +static DEFINE_MUTEX(tc_mutex); + +#define DBG_TEST(x) x +#define DBG_SPAM(x) + +#define TX_ALIGN 1 + +#define DEFAULT_TIMEOUT 10000 /* ms */ + +#if defined(CONFIG_MMC) && defined(CONFIG_STE_DMA40_DEBUG) +extern int stedma40_debug_mmc_sgsize(u32 size, bool is_chain); +#endif + +#ifdef CONFIG_STE_DMA40_DEBUG +extern void sted40_history_reset(void); +extern void sted40_history_disable(void); +extern void sted40_history_dump(void); +extern void sted40_history_text(char *text); +#else +#define sted40_history_reset() +#define sted40_history_disable() +#define sted40_history_dump() +#define sted40_history_text(x) +#endif + +enum test_case_id { + TEST1 = 1, + TEST2, + TEST3, + TEST4, + TEST5, + TEST6, + TEST7, + TEST8, + TEST9, + TEST10, + TEST11, + TEST12, + TEST13, + TEST14, + TEST15, + TEST16, + TEST17, + TEST18, + TEST19, + TEST20, + TEST21, + TEST22, + TEST23, + TEST24, + TEST25, + TEST26, + TEST27, + TEST28, + TEST29, + TEST30, + TEST31, + TEST32, + TEST33, + TEST34, + TEST35, + /* HW stress test */ + TEST36, + TEST37, + TEST38, + TEST39, + TEST40, + TEST41, + TEST42, + TEST43, + TEST44, + TEST45, + TEST46, + TEST47, + TEST48, + TEST49, + TEST50, + TEST51, + TEST52, + TEST53, + /* HW stress test end */ + TEST54, + TEST55, + TEST56, + TEST57, + TEST58, + TEST59, + TEST60, + TEST61, + TEST62, + TEST63, + TEST64, + TEST65, + TEST66, + TEST67, + TEST68, + TEST69, + NBR_TESTS, +}; + +struct tc_struct { + /* set by client */ + char name[MAX_NAME_LEN]; + int laps; + int end_padding; + int do_check_buffer; + int list_len; + + /* err status set by test engine */ + int err; + + /* used by test engine */ + int nbr_returns_per_transfer; + struct workqueue_struct *wq; + spinlock_t lock; + struct buflist buflist; + void (*callback)(struct buflist *bf); + struct work_struct work_start; + struct work_struct work_close; + struct completion done; + int job_counter; +}; + +static void tc_worker_start_single(struct work_struct *work) +{ + struct tc_struct *tc = + container_of(work, struct tc_struct, work_start); + + dmatest_buflist_start_single(&tc->buflist, tc->callback); +} + +static void tc_worker_start_sg(struct work_struct *work) +{ + struct tc_struct *tc = + container_of(work, struct tc_struct, work_start); + + dmatest_buflist_start_sg(&tc->buflist, tc->callback); +} + +static void tc_worker(struct buflist *bf) +{ + int finished_cbs; + struct tc_struct *tc = container_of(bf, struct tc_struct, buflist); + + finished_cbs = dmatest_buflist_get_nbr_finished(&tc->buflist); + + + DBG_SPAM(printk + (KERN_INFO "[%s] job_counter %d\n", __func__, + tc->job_counter)); + + tc->job_counter++; + + if (tc->job_counter == tc->nbr_returns_per_transfer) { + if (tc->do_check_buffer) + tc->err = dmatest_buflist_payload_check(&tc->buflist); + + tc->laps--; + if (tc->laps == 0) { + complete(&tc->done); + } else { + dmatest_buflist_reset_nbr_finished(&tc->buflist); + tc->job_counter = 0; + + queue_work(tc->wq, &tc->work_start); + } + } +} + +/* test wrapper functions for creating/running tests */ +static int tc_test_init(struct tc_struct *tc, bool is_sg_transfer, + int size, bool is_const_size, unsigned long dma_flags, + u32 tx_align, int timeout) +{ + int err; + + DBG_SPAM(printk(KERN_INFO "[%s] %s\n", __func__, tc->name)); + + tc->wq = create_singlethread_workqueue(tc->name); + if (tc->wq == NULL) + goto err; + err = dmatest_buflist_create(&tc->buflist, tc->list_len, + tc->end_padding, + tc->name, dma_flags, timeout, false, NULL); + if (err) + goto err_create; + + + tc->job_counter = 0; + + if (is_sg_transfer) { + INIT_WORK(&tc->work_start, tc_worker_start_sg); + tc->nbr_returns_per_transfer = 1; + } else { + tc->nbr_returns_per_transfer = tc->list_len; + INIT_WORK(&tc->work_start, tc_worker_start_single); + } + + init_completion(&tc->done); + spin_lock_init(&tc->lock); + tc->callback = tc_worker; + + if (is_const_size) + dmatest_sizelist_set(&tc->buflist, size, tx_align); + else + dmatest_sizelist_randomize(&tc->buflist, 1, 60*1024, tx_align); + dmatest_buflist_alloc(&tc->buflist); + + return 0; + err_create: + destroy_workqueue(tc->wq); + err: + return -EINVAL; +} + +static void tc_test_free(struct tc_struct *tc) +{ + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + destroy_workqueue(tc->wq); + dmatest_buflist_destroy(&tc->buflist); +} + +static void tc_test_wait(struct tc_struct *tc) +{ + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + wait_for_completion_interruptible(&tc->done); +} + +#ifdef CONFIG_STE_DMA40_DEBUG +static bool tc_test_is_done(struct tc_struct *tc) +{ + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + return completion_done(&tc->done); +} +#endif + +static void tc_test_run(struct tc_struct *tc) +{ + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + queue_work(tc->wq, &tc->work_start); +} + + +/* test case 1: Send and receive 32 byte buffer + * + */ +static int tc_1_fixed_buffer(void) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 1, + }; + int length = 1; + int end_padding = 64; + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + sted40_history_reset(); + + tc.wq = create_singlethread_workqueue(__func__); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + INIT_WORK(&tc.work_start, tc_worker_start_single); + tc.callback = tc_worker; + + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + tc.err = dmatest_buflist_create(&tc.buflist, length, end_padding, + tc.name, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, false, NULL); + + DBG_TEST(if (tc.err) printk(KERN_INFO "[%s] Error creating buflist\n", __func__)); + + if (tc.err) + goto out; + + dmatest_sizelist_set(&tc.buflist, 32, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + tc.nbr_returns_per_transfer = length; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + + out: + + return tc.err; +} + + +/* test case 2: Send and receive 1 byte buffer + * + */ +static int tc_2_fixed_buffer(void) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 100, + }; + int length = 30; + int end_padding = 64; + tc.wq = create_singlethread_workqueue(__func__); + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + tc.callback = tc_worker; + INIT_WORK(&tc.work_start, tc_worker_start_single); + + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + tc.err = dmatest_buflist_create(&tc.buflist, length, end_padding, + tc.name, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, false, NULL); + + DBG_TEST(if (tc.err) printk(KERN_INFO "[%s] Error creating buflist\n", __func__)); + + if (tc.err) + goto out; + + dmatest_sizelist_set(&tc.buflist, 32, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + tc.nbr_returns_per_transfer = length; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + out: + + return tc.err; +} + +/* test case 3: Send and receive 1k buffer + * + */ +static int tc_3_fixed_buffer(void) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 10, + }; + int length = 10; + int end_padding = 64; + tc.wq = create_singlethread_workqueue(__func__); + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + tc.callback = tc_worker; + INIT_WORK(&tc.work_start, tc_worker_start_single); + + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + dmatest_buflist_create(&tc.buflist, length, end_padding, + tc.name, DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, false, NULL); + + dmatest_sizelist_set(&tc.buflist, 1*1024, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + tc.nbr_returns_per_transfer = length; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + + return tc.err; +} + +/* test case 4: Send and receive 8k buffer + * + */ +static int tc_4_fixed_buffer(void) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 10, + }; + int length = 10; + int end_padding = 64; + tc.wq = create_singlethread_workqueue(__func__); + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + tc.callback = tc_worker; INIT_WORK(&tc.work_start, tc_worker_start_single); + + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + dmatest_buflist_create(&tc.buflist, length, end_padding, + tc.name, DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, false, NULL); + + dmatest_sizelist_set(&tc.buflist, 8*1024, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + tc.nbr_returns_per_transfer = length; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + + return tc.err; +} + +/* test case 5: Send and receive 8k buffer + * + */ +static int tc_5_random_buffer(void) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 100, + }; + int length = 40; + int end_padding = 64; + tc.wq = create_singlethread_workqueue(__func__); + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + tc.callback = tc_worker; + INIT_WORK(&tc.work_start, tc_worker_start_single); + + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + dmatest_buflist_create(&tc.buflist, length, end_padding, + tc.name, DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, false, NULL); + + dmatest_sizelist_randomize(&tc.buflist, 1, 60*1024, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + tc.nbr_returns_per_transfer = length; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + + return tc.err; +} + +/* test case 6: scatter-gatter buffer + * + */ +static int tc_sg_buffer(int scatter_list_entries, int laps, int buffer_size) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + }; + int end_padding = 64; + tc.wq = create_singlethread_workqueue(__func__); + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + tc.callback = tc_worker; + INIT_WORK(&tc.work_start, tc_worker_start_sg); + + /* test case configuration */ + tc.laps = laps; + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + tc.err = dmatest_buflist_create(&tc.buflist, scatter_list_entries, + end_padding, tc.name, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + 10*DEFAULT_TIMEOUT, false, NULL); + + DBG_TEST(if (tc.err) printk(KERN_INFO "[%s] Error creating buflist\n", __func__)); + + if (tc.err) + goto out; + + dmatest_sizelist_set(&tc.buflist, buffer_size, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + + tc.nbr_returns_per_transfer = 1; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + out: + + return tc.err; +} + +#define SCATTER_LIST_ENTRIES_MAX 25 +#define SIZE_MAX (2 * PAGE_SIZE + 100) + +static int tc_9_sg_buffer(void) +{ + int res = 0; + int scatter_list_entries; + int size; + int transfers = 0; + + sted40_history_disable(); + + for (scatter_list_entries = 1; + scatter_list_entries < SCATTER_LIST_ENTRIES_MAX; + scatter_list_entries++) { + for(size = 2; size < SIZE_MAX; size++) { + res = tc_sg_buffer(scatter_list_entries, 1, size); + if (res) { + printk(KERN_INFO "[%s] sgl with entries: %d size: %d failed\n", + __func__, scatter_list_entries, size); + goto _exit; + } + if (transfers % 2500 == 0) { + printk(KERN_INFO "[%s]: %d of %ld transfers done.\n", + __func__, transfers, + SCATTER_LIST_ENTRIES_MAX*SIZE_MAX); + } + + transfers++; + } + } +_exit: + return res; +} + +static int tc_6_sg_buffer(void) +{ + return tc_sg_buffer(4, 1, 32); +} + +#define SIZE_MAX_ETERNAL 1567 + +#if defined(CONFIG_MMC) && defined(CONFIG_STE_DMA40_DEBUG) +static int tc_14_sg_buffer_temporary_endless(void) +{ + int res = 0; + int scatter_list_entries; + int size; + int transfers = 0; + int errors = 0; + + printk(KERN_INFO "Warning:this testcase is endless and is only there to provoke memcpy sg errors\n"); + sted40_history_disable(); + while (1) { + for (scatter_list_entries = 1; + scatter_list_entries < SCATTER_LIST_ENTRIES_MAX; + scatter_list_entries++) { + for (size = 2; size < SIZE_MAX_ETERNAL; size++) { + + res = tc_sg_buffer(scatter_list_entries, 1, size); + if (res) { + errors++; + printk(KERN_INFO "[%s] sgl with entries: %d size: %d failed\n" + "after %d transfers there are %d error(s)\n", + __func__, scatter_list_entries, + size, transfers, errors); + } + transfers++; + } + } + } + + return 0; +} +#endif + +static int tc_7_sg_buffer(void) +{ + return tc_sg_buffer(200, 3, 160); +} + + +/* test case 8: scatter-gatter buffer + * + */ +static int tc_8_sg_buffer(void) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 2, + }; + int length = 16; + int end_padding = 64; + tc.wq = create_singlethread_workqueue(__func__); + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + tc.callback = tc_worker; + INIT_WORK(&tc.work_start, tc_worker_start_sg); + + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + tc.err = dmatest_buflist_create(&tc.buflist, length, end_padding, + tc.name, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, false, NULL); + + DBG_TEST(if (tc.err) printk(KERN_INFO "[%s] Error creating buflist\n", __func__)); + + if (tc.err) + goto out; + + dmatest_sizelist_set(&tc.buflist, 32, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + + /* Number of lists, not entries in each list */ + tc.nbr_returns_per_transfer = 1; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + out: + + return tc.err; +} + +#if defined(CONFIG_MMC) && defined(CONFIG_STE_DMA40_DEBUG) +static int dd_setup(struct seq_file *s, const char *func, + u32 elem_size, bool is_sg_chain, const char *cmd) +{ + int err; + + err = stedma40_debug_mmc_sgsize(elem_size, is_sg_chain); + if (err) + goto out; + err = seq_printf(s, "# [%s()] sg_elem_size %d, sg_chain %d, run:\n" + "%s; sync\n", + func, elem_size, is_sg_chain, cmd); + out: + return err; +} + +/* test case 10: Testing dma via MMC, require sdio_ops.patch + * + */ +static int tc_10_sg_size_1024_one(struct seq_file *s) +{ + u32 elem_size = 1024; + bool is_sg_chain = 0; + const char *cmd = "dd if=/dev/zero of=/out_zero bs=4096 count=1"; + DBG_SPAM(printk(KERN_INFO "# [%s]\n", __func__)); + + return dd_setup(s, __func__, elem_size, is_sg_chain, cmd); +} + +/* test case 11: Testing dma via MMC, require sdio_ops.patch + * + */ +static int tc_11_sg_size_chain_one(struct seq_file *s) +{ + u32 elem_size = 1024; + bool is_sg_chain = 1; + const char *cmd = "dd if=/dev/zero of=/out_zero bs=4096 count=1"; + + DBG_SPAM(printk(KERN_INFO "# [%s]\n", __func__)); + + return dd_setup(s, __func__, elem_size, is_sg_chain, cmd); +} + +/* test case 12: Testing dma via MMC, require sdio_ops.patch + * + */ +static int tc_12_sg_size_1024_many(struct seq_file *s) +{ + u32 elem_size = 1024; + bool is_sg_chain = 0; + const char *cmd = "dd if=/dev/zero of=/out_zero bs=4096 count=256"; + DBG_SPAM(printk(KERN_INFO "# [%s]\n", __func__)); + + return dd_setup(s, __func__, elem_size, is_sg_chain, cmd); +} + +/* test case 13: Testing dma via MMC, require sdio_ops.patch + * + */ +static int tc_13_sg_size_1024_chain_many(struct seq_file *s) +{ + u32 elem_size = 1024; + bool is_sg_chain = 1; + const char *cmd = "dd if=/dev/zero of=/out_zero bs=4096 count=256"; + DBG_SPAM(printk(KERN_INFO "# [%s]\n", __func__)); + + return dd_setup(s, __func__, elem_size, is_sg_chain, cmd); +} +#endif + +/* test case 15: Send and receive 1-4 bytes buffer + * + */ +static int tc_15_static_buffer(void) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 100, + }; + int length = 40; + int end_padding = 64; + tc.wq = create_singlethread_workqueue(__func__); + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + tc.callback = tc_worker; + INIT_WORK(&tc.work_start, tc_worker_start_single); + + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + dmatest_buflist_create(&tc.buflist, length, end_padding, + tc.name, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, false, NULL); + + dmatest_sizelist_set(&tc.buflist, 1, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + tc.nbr_returns_per_transfer = length; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + + return tc.err; +} + +/* test case 16: Send and receive 1-4 bytes buffer + * + */ +static int tc_16_static_buffer(void) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 100, + }; + int length = 40; + int end_padding = 64; + tc.wq = create_singlethread_workqueue(__func__); + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + tc.callback = tc_worker; + INIT_WORK(&tc.work_start, tc_worker_start_single); + + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + dmatest_buflist_create(&tc.buflist, length, end_padding, + tc.name, DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, false, NULL); + + dmatest_sizelist_set(&tc.buflist, 2, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + tc.nbr_returns_per_transfer = length; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + + return tc.err; +} + +/* test case 17: Send and receive 1-4 bytes buffer + * + */ +static int tc_17_static_buffer(void) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 100, + }; + int length = 40; + int end_padding = 64; + tc.wq = create_singlethread_workqueue(__func__); + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + tc.callback = tc_worker; + INIT_WORK(&tc.work_start, tc_worker_start_single); + + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + dmatest_buflist_create(&tc.buflist, length, end_padding, + tc.name, DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, false, NULL); + + dmatest_sizelist_set(&tc.buflist, 3, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + tc.nbr_returns_per_transfer = length; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + + return tc.err; +} + +/* test case 18: Send and receive 1-4 bytes buffer + * + */ +static int tc_18_static_buffer(void) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 100, + }; + int length = 40; + int end_padding = 64; + tc.wq = create_singlethread_workqueue(__func__); + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + tc.callback = tc_worker; + INIT_WORK(&tc.work_start, tc_worker_start_single); + + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + dmatest_buflist_create(&tc.buflist, length, end_padding, + tc.name, DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, false, NULL); + + dmatest_sizelist_set(&tc.buflist, 4, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + tc.nbr_returns_per_transfer = length; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + + return tc.err; +} + +/* test case 19: Send and receive 1-4 bytes buffer + * + */ +static int tc_19_static_buffer(void) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 100, + }; + int length = 40; + int end_padding = 64; + tc.wq = create_singlethread_workqueue(__func__); + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + tc.callback = tc_worker; + INIT_WORK(&tc.work_start, tc_worker_start_single); + + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + dmatest_buflist_create(&tc.buflist, length, end_padding, + tc.name, DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, false, NULL); + + dmatest_sizelist_set(&tc.buflist, 5, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + tc.nbr_returns_per_transfer = length; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + + return tc.err; +} + +/* test case 20: Send and receive 1-4 bytes buffer + * + */ +static int tc_20_random_buffer(void) +{ + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 100, + }; + int length = 40; + int end_padding = 64; + tc.wq = create_singlethread_workqueue(__func__); + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + init_completion(&tc.done); + spin_lock_init(&tc.lock); + + tc.callback = tc_worker; + INIT_WORK(&tc.work_start, tc_worker_start_single); + + snprintf(tc.name, MAX_NAME_LEN, "%s", __func__); + dmatest_buflist_create(&tc.buflist, length, end_padding, + tc.name, DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, false, NULL); + + dmatest_sizelist_randomize(&tc.buflist, 1, 4, TX_ALIGN); + + dmatest_buflist_alloc(&tc.buflist); + + tc.job_counter = 0; + tc.nbr_returns_per_transfer = length; + queue_work(tc.wq, &tc.work_start); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + destroy_workqueue(tc.wq); + + dmatest_buflist_destroy(&tc.buflist); + + return tc.err; +} + +static int tc_pause_and_unpause_parallel(int max_channels, char *str, + unsigned long dma_flags, int tx_align) +{ + struct tc_struct *tc; + int i; + int err = 0; + int bytes_left = 0; + int bytes_left_prev = 0; + int max = 1000; + int pause_id = 0; + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + tc = kzalloc(sizeof(struct tc_struct) * max_channels, GFP_KERNEL); + for (i = 0; i < max_channels; i++) { + tc[i].do_check_buffer = 1; + tc[i].laps = 1; + tc[i].end_padding = 64; + tc[i].list_len = 1; + + snprintf(tc[i].name, 32, "%s_%d", str, i); + + tc[i].err = tc_test_init(&tc[i], false, 60*1024, true, + dma_flags, tx_align, + DEFAULT_TIMEOUT); + if (tc[i].err) + break; + }; + if (i == 0) { + err = -EINVAL; + goto out; + } + max_channels = i; + + DBG_SPAM(printk(KERN_INFO "[%s] max available memcpy channels %d\n", str, max_channels)); + + for (i = 0; i < max_channels; i++) + tc_test_run(&tc[i]); + + + for (i = 0; i < max; i++) { + { + struct dma_tx_state state; + + tc[pause_id].buflist.dma_chan->device-> + device_control(tc[pause_id].buflist.dma_chan, + DMA_PAUSE, 0); + + (void) tc[pause_id].buflist.dma_chan->device-> + device_tx_status(tc[pause_id].buflist.dma_chan, + tc[pause_id].buflist.cookie[0], + &state); + bytes_left = state.residue; + } + + + + if (bytes_left > 0) + break; + } + if (i == max) { + DBG_SPAM(printk(KERN_INFO "[%s] i == max bytes left %d\n", + __func__, bytes_left)); + goto wait; + } + + DBG_SPAM(printk(KERN_INFO "[%s] bytes left %d\n", + __func__, bytes_left)); + tc[pause_id].buflist.dma_chan->device-> + device_control(tc[pause_id].buflist.dma_chan, + DMA_RESUME, 0); + + do { + mdelay(1); + tc[pause_id].buflist.dma_chan->device-> + device_control(tc[pause_id].buflist.dma_chan, + DMA_PAUSE, 0); + bytes_left_prev = bytes_left; + + { + struct dma_tx_state state; + + (void) tc[pause_id].buflist.dma_chan->device-> + device_tx_status(tc[pause_id].buflist.dma_chan, + tc[pause_id].buflist.cookie[0], + &state); + bytes_left = state.residue; + + } + tc[pause_id].buflist.dma_chan->device-> + device_control(tc[pause_id].buflist.dma_chan, + DMA_RESUME, 0); + } while (bytes_left != 0 || bytes_left_prev != bytes_left); + + if (bytes_left != 0 && bytes_left_prev == bytes_left) { + DBG_SPAM(printk(KERN_INFO "[%s] bytes left = prev %d\n", + __func__, bytes_left)); + tc[pause_id].err = -EINVAL; + goto out; + } + + + DBG_SPAM(printk(KERN_INFO "[%s] bytes left %d\n", + __func__, bytes_left)); + + wait: + for (i = 0; i < max_channels; i++) { + tc_test_wait(&tc[i]); + DBG_SPAM(printk(KERN_INFO "[%s] %d done\n", str, i)); + } + + out: + for (i = 0; i < max_channels; i++) + tc_test_free(&tc[i]); + + for (i = 0; i < max_channels; i++) + err |= tc[i].err; + + kfree(tc); + return err; +} + +static int tc_21_stop_and_go(void) +{ + return tc_pause_and_unpause_parallel(1, "tc_21", + DMA_PREP_INTERRUPT | DMA_CTRL_ACK, 4); +} + +static struct dma_chan *tc_22_25_chan; +int tc_22_req(void) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_MEMCPY, mask); + + tc_22_25_chan = dma_request_channel(mask, NULL, NULL); + + if (tc_22_25_chan != NULL) + return 0; + else + return -EINVAL; +} + +static struct dma_chan *tc_22_25_chan; +int tc_23_no_irq(void) +{ + dma_cap_mask_t mask; + void *buf_src; + void *buf_dst; + dma_addr_t addr_src; + dma_addr_t addr_dst; + int size = 4096; + struct dma_async_tx_descriptor *desc; + + if (tc_22_25_chan == NULL) + return -EINVAL; + + dma_cap_zero(mask); + dma_cap_set(DMA_MEMCPY, mask); + + buf_src = kzalloc(size, GFP_KERNEL); + memset(buf_src, 0xAA, size); + buf_dst = kzalloc(size, GFP_KERNEL); + + addr_src = dma_map_single(tc_22_25_chan->device->dev, + buf_src, size, DMA_BIDIRECTIONAL); + addr_dst = dma_map_single(tc_22_25_chan->device->dev, + buf_dst, size, DMA_FROM_DEVICE); + + desc = tc_22_25_chan->device-> + device_prep_dma_memcpy(tc_22_25_chan, + addr_dst, addr_src, size, + DMA_CTRL_ACK); + + desc->tx_submit(desc); + dma_async_issue_pending(tc_22_25_chan); + + msleep(1000); + + dma_unmap_single(tc_22_25_chan->device->dev, + addr_src, size, DMA_BIDIRECTIONAL); + + dma_unmap_single(tc_22_25_chan->device->dev, + addr_dst, size, DMA_FROM_DEVICE); + + if (memcmp(buf_src, buf_dst, size) == 0) + return 0; + else + return -EINVAL; +} + + +static void tc_24_transmit_cb(void *data) +{ + struct tc_struct *tc = data; + complete(&tc->done); +} + +int tc_24_irq(void) +{ + dma_cap_mask_t mask; + dma_addr_t addr_src; + dma_addr_t addr_dst; + int size = 4096; + void *buf_src; + void *buf_dst; + + struct tc_struct tc = { + .do_check_buffer = 1, + .laps = 1, + }; + struct dma_async_tx_descriptor *desc; + init_completion(&tc.done); + + if (tc_22_25_chan == NULL) + return -EINVAL; + + dma_cap_zero(mask); + dma_cap_set(DMA_MEMCPY, mask); + + buf_src = kzalloc(size, GFP_KERNEL); + memset(buf_src, 0xAA, size); + buf_dst = kzalloc(size, GFP_KERNEL); + + addr_src = dma_map_single(tc_22_25_chan->device->dev, + buf_src, size, DMA_BIDIRECTIONAL); + addr_dst = dma_map_single(tc_22_25_chan->device->dev, + buf_dst, size, DMA_FROM_DEVICE); + + desc = tc_22_25_chan->device-> + device_prep_dma_memcpy(tc_22_25_chan, + addr_dst, addr_src, size, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + + desc->callback = tc_24_transmit_cb; + desc->callback_param = &tc; + desc->tx_submit(desc); + + + dma_async_issue_pending(tc_22_25_chan); + + /* block here until test case finished */ + wait_for_completion_interruptible(&tc.done); + + dma_unmap_single(tc_22_25_chan->device->dev, + addr_src, size, DMA_BIDIRECTIONAL); + + dma_unmap_single(tc_22_25_chan->device->dev, + addr_dst, size, DMA_FROM_DEVICE); + + if (memcmp(buf_src, buf_dst, size) == 0) { + kfree(buf_src); + kfree(buf_dst); + return 0; + } else { + kfree(buf_src); + kfree(buf_dst); + return -EINVAL; + } +} + +int tc_25_free(void) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_MEMCPY, mask); + + if (tc_22_25_chan == NULL) + return -EINVAL; + + dma_release_channel(tc_22_25_chan); + tc_22_25_chan = NULL; + + return 0; +} + +struct tc_parallel { + char str[32]; + int max_channels; + int laps; + unsigned long dma_flags; + int chan_start_index; + int tx_align; + int const_size; + int list_len; + int timeout; +}; + +static int tc_run_parallel(struct tc_parallel *tcp) +{ + struct tc_struct *tc; + int i; + int err = 0; + int max_channels; + bool use_const_size = tcp->const_size != -1; + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + tc = kzalloc(sizeof(struct tc_struct) * tcp->max_channels, GFP_KERNEL); + for (i = 0; i < tcp->max_channels; i++) { + tc[i].do_check_buffer = 1; + tc[i].laps = tcp->laps; + tc[i].end_padding = 64; + tc[i].list_len = tcp->list_len; + + snprintf(tc[i].name, 32, "%s_%d", tcp->str, i); + + tc[i].err = tc_test_init(&tc[i], false, tcp->const_size, + use_const_size, tcp->dma_flags, + tcp->tx_align, tcp->timeout); + if (tc[i].err) + break; + }; + if (i == 0) { + err = -EINVAL; + goto out; + } + max_channels = i; + + DBG_SPAM(printk(KERN_INFO "[%s] max available memcpy channels %d\n", tcp->str, + max_channels)); + + for (i = tcp->chan_start_index; i < max_channels; i++) { + DBG_SPAM(printk(KERN_INFO "starting %d\n", i)); + tc_test_run(&tc[i]); + } + + for (i = tcp->chan_start_index; i < max_channels; i++) { + tc_test_wait(&tc[i]); + DBG_SPAM(printk(KERN_INFO "[%s] %d done\n", tcp->str, i)); + } + + for (i = 0; i < max_channels; i++) + tc_test_free(&tc[i]); + + for (i = 0; i < max_channels; i++) + err |= tc[i].err; + + out: + kfree(tc); + return err; +} + +static int tc_26_run_3_parallel(void) +{ + struct tc_parallel tcp = { + .str = "tc_26", + .max_channels = 3, + .laps = 20, + .dma_flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + .chan_start_index = 0, + .tx_align = 1, + .const_size = -1, + .list_len = 30, + .timeout = DEFAULT_TIMEOUT, + }; + + return tc_run_parallel(&tcp); +} + +static int tc_27_run_4_parallel(void) +{ + struct tc_parallel tcp = { + .str = "tc_27", + .max_channels = 4, + .laps = 20, + .dma_flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + .chan_start_index = 0, + .tx_align = 1, + .const_size = -1, + .list_len = 30, + .timeout = DEFAULT_TIMEOUT, + }; + + return tc_run_parallel(&tcp); +} + +static int tc_28_run_5_parallel(void) +{ + struct tc_parallel tcp = { + .str = "tc_28", + .max_channels = 5, + .laps = 20, + .dma_flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + .chan_start_index = 0, + .tx_align = 1, + .const_size = -1, + .list_len = 30, + .timeout = DEFAULT_TIMEOUT, + }; + + return tc_run_parallel(&tcp); +} + +static int tc_29_run_6_parallel(void) +{ + struct tc_parallel tcp = { + .str = "tc_29", + .max_channels = 6, + .laps = 20, + .dma_flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + .chan_start_index = 0, + .tx_align = 1, + .const_size = -1, + .list_len = 30, + .timeout = DEFAULT_TIMEOUT, + }; + + return tc_run_parallel(&tcp); + +} + +static int tc_30_run_7_parallel(void) +{ + struct tc_parallel tcp = { + .str = "tc_30", + .max_channels = 7, + .laps = 20, + .dma_flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + .chan_start_index = 0, + .tx_align = 1, + .const_size = -1, + .list_len = 30, + .timeout = DEFAULT_TIMEOUT, + }; + + return tc_run_parallel(&tcp); + +} + +static int tc_31_run_128_parallel(void) +{ + struct tc_parallel tcp = { + .str = "tc_31", + .max_channels = 128, + .laps = 20, + .dma_flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + .chan_start_index = 0, + .tx_align = 1, + .const_size = -1, + .list_len = 30, + .timeout = DEFAULT_TIMEOUT, + }; + + return tc_run_parallel(&tcp); +} + +static int tc_32_run_1_parallel(void) +{ + struct tc_parallel tcp = { + .str = "tc_32", + .max_channels = 1, + .laps = 20, + .dma_flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + .chan_start_index = 0, + .tx_align = 1, + .const_size = -1, + .list_len = 30, + .timeout = DEFAULT_TIMEOUT, + }; + + return tc_run_parallel(&tcp); +} + +static int tc_33_run_2_parallel(void) +{ + struct tc_parallel tcp = { + .str = "tc_33", + .max_channels = 2, + .laps = 20, + .dma_flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + .chan_start_index = 0, + .tx_align = 1, + .const_size = -1, + .list_len = 30, + .timeout = DEFAULT_TIMEOUT, + }; + + return tc_run_parallel(&tcp); + +} + +static int tc_34_run_pause_and_unpause_parallel(void) +{ + return tc_pause_and_unpause_parallel(4, "tc_34", + DMA_PREP_INTERRUPT | DMA_CTRL_ACK, 1); +} + +static int tc_35_run_1_parallel_reuse(void) +{ + struct tc_parallel tcp = { + .str = "tc_35", + .max_channels = 1, + .laps = 20, + .dma_flags = DMA_PREP_INTERRUPT, + .chan_start_index = 0, + .tx_align = 1, + .const_size = -1, + .list_len = 30, + .timeout = 100*DEFAULT_TIMEOUT, + }; + + return tc_run_parallel(&tcp); + +} + +enum read_reg_type { + DMA_TC_READ_PHY_CHAN_1 = 1 << 0, + DMA_TC_READ_PHY_CHAN_2 = 1 << 1, + DMA_TC_READ_PHY_CHAN_3 = 1 << 2, + DMA_TC_READ_PHY_CHAN_4 = 1 << 3, + DMA_TC_READ_PHY_CHAN_5 = 1 << 4, + DMA_TC_READ_PHY_CHAN_6 = 1 << 5, + DMA_TC_READ_PHY_CHAN_7 = 1 << 6, + DMA_TC_READ_PHY_CHAN_8 = 1 << 7, + DMA_TC_READ_GLOBAL = 1 << 8, +}; + + +#ifdef CONFIG_STE_DMA40_DEBUG +extern void stedma40_debug_read_chan(int chan, u32 *cfg); +extern void stedma40_debug_read_global_conf(u32 *cfg); +static void tc_read_reg(unsigned long read_type) +{ + u32 cfg = 0; + + if (read_type | DMA_TC_READ_PHY_CHAN_1) + stedma40_debug_read_chan(0, &cfg); + if (read_type | DMA_TC_READ_PHY_CHAN_2) + stedma40_debug_read_chan(1, &cfg); + if (read_type | DMA_TC_READ_PHY_CHAN_3) + stedma40_debug_read_chan(2, &cfg); + if (read_type | DMA_TC_READ_PHY_CHAN_4) + stedma40_debug_read_chan(3, &cfg); + if (read_type | DMA_TC_READ_PHY_CHAN_5) + stedma40_debug_read_chan(4, &cfg); + if (read_type | DMA_TC_READ_PHY_CHAN_6) + stedma40_debug_read_chan(5, &cfg); + if (read_type | DMA_TC_READ_PHY_CHAN_7) + stedma40_debug_read_chan(6, &cfg); + if (read_type | DMA_TC_READ_PHY_CHAN_8) + stedma40_debug_read_chan(7, &cfg); + if (read_type | DMA_TC_READ_GLOBAL) + stedma40_debug_read_global_conf(&cfg); +} + + +int tc_run_while_read_reg(char *str, int max_channels, int size, int list_len, + int laps, bool is_sg, bool is_const_size, + unsigned long dma_flags, unsigned long read_type) +{ + struct tc_struct *tc; + int i; + int err = 0; + + DBG_SPAM(printk(KERN_INFO "[%s]\n", __func__)); + + sted40_history_disable(); + + tc = kzalloc(sizeof(struct tc_struct) * max_channels, GFP_KERNEL); + for (i = 0; i < max_channels; i++) { + tc[i].do_check_buffer = 1; + tc[i].laps = laps; + tc[i].end_padding = 64; + tc[i].list_len = list_len; + + snprintf(tc[i].name, 32, "%s_%d", str, i); + + tc[i].err = tc_test_init(&tc[i], is_sg, size, is_const_size, + dma_flags, TX_ALIGN, + DEFAULT_TIMEOUT); + if (tc[i].err) + break; + }; + if (i == 0) { + err = -EINVAL; + goto out; + } + max_channels = i; + + DBG_SPAM(printk(KERN_INFO "[%s] max available memcpy channels %d\n", str, max_channels)); + + for (i = 0; i < max_channels; i++) + tc_test_run(&tc[i]); + + for (i = 0; i < max_channels; i++) { + while (!tc_test_is_done(&tc[i])) + tc_read_reg(read_type); + DBG_SPAM(printk(KERN_INFO "[%s] %d done\n", str, i)); + } + + for (i = 0; i < max_channels; i++) + tc_test_free(&tc[i]); + + for (i = 0; i < max_channels; i++) + err |= tc[i].err; + +out: + kfree(tc); + return err; +} + +static int tc_36(void) +{ + return tc_run_while_read_reg("tc_36", 1, 1024, 30, 10, true, true, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_1); +} +static int tc_37(void) +{ + return tc_run_while_read_reg("tc_37", 1, 1024, 30, 10, true, true, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_2); +} +static int tc_38(void) +{ + return tc_run_while_read_reg("tc_38", 1, 1024, 30, 10, true, true, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_3); +} +static int tc_39(void) +{ + return tc_run_while_read_reg("tc_39", 1, 1024, 30, 10, true, true, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_4); +} +static int tc_40(void) +{ + return tc_run_while_read_reg("tc_40", 1, 1024, 30, 10, true, true, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_5); +} +static int tc_41(void) +{ + return tc_run_while_read_reg("tc_41", 1, 1024, 30, 10, true, true, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_6); +} +static int tc_42(void) +{ + return tc_run_while_read_reg("tc_42", 1, 1024, 30, 10, true, true, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_7); +} +static int tc_43(void) +{ + return tc_run_while_read_reg("tc_43", 1, 1024, 30, 10, true, true, + DMA_PREP_INTERRUPT, + DMA_TC_READ_GLOBAL); +} +static int tc_44(void) +{ + return tc_run_while_read_reg("tc_44", 1, 1024, 30, 10, true, true, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_1 | + DMA_TC_READ_PHY_CHAN_2 | + DMA_TC_READ_PHY_CHAN_3 | + DMA_TC_READ_PHY_CHAN_4 | + DMA_TC_READ_PHY_CHAN_5 | + DMA_TC_READ_PHY_CHAN_6 | + DMA_TC_READ_PHY_CHAN_7 | + DMA_TC_READ_GLOBAL); +} +static int tc_45(void) +{ + return tc_run_while_read_reg("tc_45", 1, 1024, 30, 10, true, false, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_1 | + DMA_TC_READ_PHY_CHAN_2 | + DMA_TC_READ_PHY_CHAN_3 | + DMA_TC_READ_PHY_CHAN_4 | + DMA_TC_READ_PHY_CHAN_5 | + DMA_TC_READ_PHY_CHAN_6 | + DMA_TC_READ_PHY_CHAN_7 | + DMA_TC_READ_GLOBAL); +} +static int tc_46(void) +{ + return tc_run_while_read_reg("tc_46", 1, 128, 100, 10, true, true, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_1 | + DMA_TC_READ_PHY_CHAN_2 | + DMA_TC_READ_PHY_CHAN_3 | + DMA_TC_READ_PHY_CHAN_4 | + DMA_TC_READ_PHY_CHAN_5 | + DMA_TC_READ_PHY_CHAN_6 | + DMA_TC_READ_PHY_CHAN_7 | + DMA_TC_READ_GLOBAL); +} +static int tc_47(void) +{ + return tc_run_while_read_reg("tc_47", 1, 128, 100, 10, true, false, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_1 | + DMA_TC_READ_PHY_CHAN_2 | + DMA_TC_READ_PHY_CHAN_3 | + DMA_TC_READ_PHY_CHAN_4 | + DMA_TC_READ_PHY_CHAN_5 | + DMA_TC_READ_PHY_CHAN_6 | + DMA_TC_READ_PHY_CHAN_7 | + DMA_TC_READ_GLOBAL); +} +static int tc_48(void) +{ + return tc_run_while_read_reg("tc_48", 1, 128, 200, 1000, true, true, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_1 | + DMA_TC_READ_PHY_CHAN_2 | + DMA_TC_READ_PHY_CHAN_3 | + DMA_TC_READ_PHY_CHAN_4 | + DMA_TC_READ_PHY_CHAN_5 | + DMA_TC_READ_PHY_CHAN_6 | + DMA_TC_READ_PHY_CHAN_7 | + DMA_TC_READ_GLOBAL); +} +static int tc_49(void) +{ + return tc_run_while_read_reg("tc_49", 1, 128, 200, 1000, true, false, + DMA_PREP_INTERRUPT, + DMA_TC_READ_PHY_CHAN_1 | + DMA_TC_READ_PHY_CHAN_2 | + DMA_TC_READ_PHY_CHAN_3 | + DMA_TC_READ_PHY_CHAN_4 | + DMA_TC_READ_PHY_CHAN_5 | + DMA_TC_READ_PHY_CHAN_6 | + DMA_TC_READ_PHY_CHAN_7 | + DMA_TC_READ_GLOBAL); +} +#endif + +static int tc_50(void) +{ + struct tc_parallel tcp = { + .str = "tc_50", + .max_channels = 5, + .laps = 200, + .dma_flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + .chan_start_index = 3, + .tx_align = 4, + .const_size = -1, + .list_len = 30, + .timeout = DEFAULT_TIMEOUT, + }; + + return tc_run_parallel(&tcp); +} + +static int tc_51(void) +{ + return tc_pause_and_unpause_parallel(2, "tc_51", + DMA_PREP_INTERRUPT | DMA_CTRL_ACK, 4); +} + +static int tc_52(void) +{ + return tc_pause_and_unpause_parallel(4, "tc_52", + DMA_PREP_INTERRUPT | DMA_CTRL_ACK, 4); +} + +static int tc_53(void) +{ + struct tc_parallel tcp = { + .str = "tc_53", + .max_channels = 5, + .laps = 200, + .dma_flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + .chan_start_index = 3, + .tx_align = 1, + .const_size = -1, + .list_len = 30, + .timeout = DEFAULT_TIMEOUT, + }; + + return tc_run_parallel(&tcp); + +} + +static int tc_54_trigger(void) +{ + struct tc_parallel tcp = { + .str = "tc_54", + .max_channels = 5, + .laps = 1, + .dma_flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + .chan_start_index = 0, + .tx_align = 1, + .const_size = 1024, + .list_len = 4, /* Must >2 to tigger error, when we had 4 log + memcpy channsl */ + .timeout = 1000, /* 1s*/ + }; + + return tc_run_parallel(&tcp); +} + +struct tc_link_cfg { + int tc; + int jobs; + int links; + int buffer_size; + bool request_phys; + bool start_in_sequence; + bool slow_start; + /* randomize */ + u32 min_size; + u32 max_size; +}; + +struct tc_link { + struct buflist buflist; + struct completion done; + struct dma_async_tx_descriptor *desc; +}; + + +static void tc_link_callback(void *data) +{ + struct tc_link *tc = data; + complete(&tc->done); +} + +/* used for testing job linking */ +static int tc_link_core(struct tc_link_cfg *cfg) +{ + + int i; + int err = 0; + char name[MAX_NAME_LEN]; + struct dma_chan *dma_chan = NULL; + + struct tc_link *tc; + + + tc = kmalloc(cfg->jobs * sizeof(struct tc_link), GFP_KERNEL); + if (!tc) + goto done; + + for (i = 0 ; i < cfg->jobs; i++) { + + snprintf(name, MAX_NAME_LEN - 1, "%s_tc_%d_%.2d", + __func__, cfg->tc, i); + err = dmatest_buflist_create(&tc[i].buflist, cfg->links, 0, + name, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK, + DEFAULT_TIMEOUT, cfg->request_phys, + dma_chan); + if (err) + /* Leaks previous allocated buflists */ + goto done; + if (cfg->min_size && cfg->max_size) + dmatest_sizelist_randomize(&tc->buflist, cfg->min_size, + cfg->max_size, TX_ALIGN); + else + dmatest_sizelist_set(&tc[i].buflist, cfg->buffer_size, + TX_ALIGN); + + dmatest_buflist_alloc(&tc[i].buflist); + + dma_chan = tc[i].buflist.dma_chan; + + tc[i].buflist.sgl_src_len = + dma_map_sg(tc[i].buflist.dma_chan->device->dev, + tc[i].buflist.sgl_src, + tc[i].buflist.list_len, + DMA_BIDIRECTIONAL); + tc[i].buflist.sgl_dst_len = + dma_map_sg(tc[i].buflist.dma_chan->device->dev, + tc[i].buflist.sgl_dst, + tc[i].buflist.list_len, + /* Both direction for verifying transfered data */ + DMA_BIDIRECTIONAL); + + tc[i].desc = dma_chan->device->device_prep_dma_sg(dma_chan, + tc[i].buflist.sgl_dst, + tc[i].buflist.sgl_dst_len, + tc[i].buflist.sgl_src, + tc[i].buflist.sgl_src_len, + tc[i].buflist.dma_engine_flags); + init_completion(&tc[i].done); + tc[i].desc->callback = tc_link_callback; + tc[i].desc->callback_param = &tc[i]; + } + + if (cfg->start_in_sequence) { + for (i = 0; i < cfg->jobs; i++) { + tc[i].desc->tx_submit(tc[i].desc); + dma_async_issue_pending(dma_chan); + + if (cfg->slow_start) + udelay(500); + } + } else { + + for (i = 0; i < cfg->jobs; i++) + tc[i].desc->tx_submit(tc[i].desc); + + dma_async_issue_pending(dma_chan); + } + + for (i = 0; i < cfg->jobs; i++) { + wait_for_completion_interruptible(&tc[i].done); + err |= dmatest_buflist_payload_check(&tc[i].buflist); + } + + for (i = 0; i < cfg->jobs; i++) { + tc[i].buflist.dma_chan = dma_chan; + dmatest_buflist_destroy(&tc[i].buflist); + dma_chan = NULL; + } +done: + kfree(tc); + return err; +} + +static int tc_55(void) +{ + /* Link 2 jobs in hw before start transfer (physical) */ + struct tc_link_cfg tc_cfg = { + .tc = 55, + .jobs = 2, + .links = 5, /* Just > 1 is enough */ + .buffer_size = SZ_4K, /* Just something big */ + .request_phys = true, + .start_in_sequence = false, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_56(void) +{ + /* Link 2 jobs in hw after first job has started (physical) */ + struct tc_link_cfg tc_cfg = { + .tc = 56, + .jobs = 2, + .links = 5, /* Just > 1 is enough */ + .buffer_size = SZ_4K, /* Just something big */ + .request_phys = true, + .start_in_sequence = true, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_57(void) +{ + /* Link 2 jobs in hw after first job has started (physical) */ + struct tc_link_cfg tc_cfg = { + .tc = 57, + .jobs = 2, + .links = 1, /* No links */ + .buffer_size = SZ_16K, /* Just something big */ + .request_phys = true, + .start_in_sequence = true, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_58(void) +{ + /* Link 10 jobs in hw after first job has started (physical) */ + struct tc_link_cfg tc_cfg = { + .tc = 58, + .jobs = 10, + .links = 1, /* No links */ + .buffer_size = SZ_16K, /* Just something big */ + .request_phys = true, + .start_in_sequence = true, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_59(void) +{ + /* Link 10 jobs in hw after first job has started (physical) */ + struct tc_link_cfg tc_cfg = { + .tc = 59, + .jobs = 10, + .links = 10, + .buffer_size = SZ_4K, /* Just something big */ + .request_phys = true, + .start_in_sequence = true, + }; + + return tc_link_core(&tc_cfg); +} + + +static int tc_60(void) +{ + /* Link 2 jobs in hw before start transfer (logical) */ + struct tc_link_cfg tc_cfg = { + .tc = 60, + .jobs = 2, + .links = 2, /* Just > 1 is enough */ + .buffer_size = 4096, /* Just something big */ + .request_phys = false, + .start_in_sequence = false, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_61(void) +{ + /* Link 2 jobs in hw after first job has started (logical) */ + struct tc_link_cfg tc_cfg = { + .tc = 61, + .jobs = 2, + .links = 2, /* Just > 1 is enough */ + .buffer_size = 4096, /* Just something big */ + .request_phys = false, + .start_in_sequence = true, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_62(void) +{ + /* + * Test to transfer a logical job with >64 links (Out of lcla space + * then.) + */ + struct tc_link_cfg tc_cfg = { + .tc = 62, + .jobs = 1, + .links = 90, + .buffer_size = 128, + .request_phys = false, + .start_in_sequence = true, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_63(void) +{ + /* + * Test to transfer a logical job with >124 links (Out of lcla space + * then.) + */ + struct tc_link_cfg tc_cfg = { + .tc = 63, + .jobs = 1, + .links = 140, + .buffer_size = 128, + .request_phys = false, + .start_in_sequence = true, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_64(void) +{ + /* Test allocate 4 80 lli long jobs before starting */ + struct tc_link_cfg tc_cfg = { + .tc = 64, + .jobs = 4, + .links = 80, + .buffer_size = 128, + .request_phys = false, + .start_in_sequence = false, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_65(void) +{ + /* Link 10 jobs in hw after first job has started (logical) */ + struct tc_link_cfg tc_cfg = { + .tc = 59, + .jobs = 10, + .links = 10, + .buffer_size = SZ_4K, /* Just something big */ + .request_phys = false, + .start_in_sequence = true, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_66(void) +{ + /* + * Link 10 jobs in hw after first job has started (logical), + * no links + */ + struct tc_link_cfg tc_cfg = { + .tc = 58, + .jobs = 10, + .links = 1, /* No links */ + .buffer_size = SZ_16K, /* Just something big */ + .request_phys = false, + .start_in_sequence = true, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_67(void) +{ + /* Link 10 jobs in hw after first job has started (logical), slowly */ + struct tc_link_cfg tc_cfg = { + .tc = 59, + .jobs = 10, + .links = 10, + .buffer_size = SZ_4K, /* Just something big */ + .request_phys = false, + .start_in_sequence = true, + .slow_start = true, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_68(void) +{ + /* Link 10 jobs in hw after first job has started (physical), slowly */ + struct tc_link_cfg tc_cfg = { + .tc = 59, + .jobs = 10, + .links = 10, + .buffer_size = SZ_4K, /* Just something big */ + .request_phys = true, + .start_in_sequence = true, + .slow_start = true, + }; + + return tc_link_core(&tc_cfg); +} + +static int tc_69(void) +{ + int err = 0; + int i; + + /* Test large transfer than 64k */ + struct tc_link_cfg tc_cfg[] = { + { + .tc = 69, + .jobs = 1, + .links = 10, + .buffer_size = 0x10000 - 1, + }, + { + .tc = 69, + .jobs = 1, + .links = 10, + .buffer_size = 0x10000, + }, + { + .tc = 69, + .jobs = 1, + .links = 10, + .buffer_size = 0x10000 + 1, + }, + { + .tc = 69, + .jobs = 1, + .links = 10, + .buffer_size = 2*0x10000 - 1, + }, + { + .tc = 69, + .jobs = 1, + .links = 10, + .buffer_size = 2*0x10000, + }, + { + .tc = 69, + .jobs = 1, + .links = 10, + .buffer_size = 2*0x10000 + 1, + }, + }; + for (i = 0; i < ARRAY_SIZE(tc_cfg); i++) { + printk(KERN_INFO "[%s] %d out of %d\n", __func__, + i, ARRAY_SIZE(tc_cfg)); + err = tc_link_core(&tc_cfg[i]); + if (err) + goto out; + } + + out: + return err; +} + +static int tc_nop(struct seq_file *s, int id) +{ + int err; + err = seq_printf(s, "TEST_%d is removed\n", id); + return err; +} + +static int d40_test_run(struct seq_file *s, void *iter) +{ + int test_id = (int) s->private; + int err = -EINVAL; + char *str = ""; + + err = mutex_lock_interruptible(&tc_mutex); + + /* the out put from these tests are actually a test script + * echo is needed in order to display the result + */ +#if defined(CONFIG_MMC) && defined(CONFIG_STE_DMA40_DEBUG) + switch (test_id) { + case TEST10: + case TEST11: + case TEST12: + case TEST13: + str = "echo "; + break; + } +#endif + if (err) + goto out; + + switch (test_id) { + case TEST1: + err = tc_1_fixed_buffer(); + break; + case TEST2: + err = tc_2_fixed_buffer(); + break; + case TEST3: + err = tc_3_fixed_buffer(); + break; + case TEST4: + err = tc_4_fixed_buffer(); + break; + case TEST5: + err = tc_5_random_buffer(); + break; + case TEST6: + err = tc_6_sg_buffer(); + break; + case TEST7: + err = tc_7_sg_buffer(); + break; + case TEST8: + err = tc_8_sg_buffer(); + break; + case TEST9: + err = tc_9_sg_buffer(); + break; +#if defined(CONFIG_MMC) && defined(CONFIG_STE_DMA40_DEBUG) + case TEST10: + err = tc_10_sg_size_1024_one(s); + str = "echo "; + break; + case TEST11: + err = tc_11_sg_size_chain_one(s); + str = "echo "; + break; + case TEST12: + err = tc_12_sg_size_1024_many(s); + str = "echo "; + break; + case TEST13: + err = tc_13_sg_size_1024_chain_many(s); + str = "echo "; + break; + case TEST14: + err = tc_14_sg_buffer_temporary_endless(); + break; +#else + case TEST10: + case TEST11: + case TEST12: + case TEST13: + case TEST14: + err = tc_nop(s, test_id); + break; +#endif + case TEST15: + err = tc_15_static_buffer(); + break; + case TEST16: + err = tc_16_static_buffer(); + break; + case TEST17: + err = tc_17_static_buffer(); + break; + case TEST18: + err = tc_18_static_buffer(); + break; + case TEST19: + err = tc_19_static_buffer(); + break; + case TEST20: + err = tc_20_random_buffer(); + break; + case TEST21: + err = tc_21_stop_and_go(); + break; + case TEST22: + case TEST23: + case TEST24: + case TEST25: + err = tc_22_req(); + if (!err) + err = tc_23_no_irq(); + if (!err) + err = tc_24_irq(); + if (!err) + err = tc_25_free(); + break; + case TEST26: + err = tc_26_run_3_parallel(); + break; + case TEST27: + err = tc_27_run_4_parallel(); + break; + case TEST28: + err = tc_28_run_5_parallel(); + break; + case TEST29: + err = tc_29_run_6_parallel(); + break; + case TEST30: + err = tc_30_run_7_parallel(); + break; + case TEST31: + err = tc_31_run_128_parallel(); + break; + case TEST32: + err = tc_32_run_1_parallel(); + break; + case TEST33: + err = tc_33_run_2_parallel(); + break; + case TEST34: + err = tc_34_run_pause_and_unpause_parallel(); + break; + case TEST35: + err = tc_35_run_1_parallel_reuse(); + break; + +#ifdef CONFIG_STE_DMA40_DEBUG + case TEST36: + err = tc_36(); + break; + case TEST37: + err = tc_37(); + break; + case TEST38: + err = tc_38(); + break; + case TEST39: + err = tc_39(); + break; + case TEST40: + err = tc_40(); + break; + case TEST41: + err = tc_41(); + break; + case TEST42: + err = tc_42(); + break; + case TEST43: + err = tc_43(); + break; + case TEST44: + err = tc_44(); + break; + case TEST45: + err = tc_45(); + break; + case TEST46: + err = tc_46(); + break; + case TEST47: + err = tc_47(); + break; + case TEST48: + err = tc_48(); + break; + case TEST49: + err = tc_49(); + break; +#else + case TEST36: + case TEST37: + case TEST38: + case TEST39: + case TEST40: + case TEST41: + case TEST42: + case TEST43: + case TEST44: + case TEST45: + case TEST46: + case TEST47: + case TEST48: + case TEST49: + err = tc_nop(s, test_id); + break; +#endif + case TEST50: + err = tc_50(); + break; + case TEST51: + err = tc_51(); + break; + case TEST52: + err = tc_52(); + break; + case TEST53: + err = tc_53(); + break; + case TEST54: + err = tc_54_trigger(); + break; + case TEST55: + err = tc_55(); + break; + case TEST56: + err = tc_56(); + break; + case TEST57: + err = tc_57(); + break; + case TEST58: + err = tc_58(); + break; + case TEST59: + err = tc_59(); + break; + case TEST60: + err = tc_60(); + break; + case TEST61: + err = tc_61(); + break; + case TEST62: + err = tc_62(); + break; + case TEST63: + err = tc_63(); + break; + case TEST64: + err = tc_64(); + break; + case TEST65: + err = tc_65(); + break; + case TEST66: + err = tc_66(); + break; + case TEST67: + err = tc_67(); + break; + case TEST68: + err = tc_68(); + break; + case TEST69: + err = tc_69(); + break; + + default: + err = -EINVAL; + printk(KERN_INFO "# [%s] Invalid test id %d\n", __func__, + test_id); + } + +out: + seq_printf(s, "%sFinished test %d: %s\n", str, test_id, + err == 0 ? "OK" : "***FAIL***"); + + mutex_unlock(&tc_mutex); + return 0; +} + + +static struct dentry *debugfs_dir; + +static int d40_debugfs_open(struct inode *inode, + struct file *file) +{ + int err; + + err = single_open(file, + d40_test_run, + inode->i_private); + + return err; +} + +static const struct file_operations d40_debugfs_ops = { + .open = d40_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init stedma40_test_init(void) +{ + char name[32]; + int i; + int err = 0; + void *err_ptr = NULL; + + err = mutex_lock_interruptible(&tc_mutex); + if (err) + goto err; + + printk(KERN_INFO "[%s] dma-test-module build: %s %s nbr tests %d\n", + __func__, __DATE__, __TIME__, NBR_TESTS - 1); + + debugfs_dir = debugfs_create_dir("ste_dma40_test", NULL); + if (IS_ERR(debugfs_dir)) { + err = PTR_ERR(debugfs_dir); + goto out; + } + + for (i = 1; i < NBR_TESTS; i++) { + err = snprintf(name, 32, "test_%d", i); + if (err < 0) + goto out; + err = 0; + + err_ptr = debugfs_create_file(name, + S_IFREG | S_IRUGO, + debugfs_dir, (void *)i, + &d40_debugfs_ops); + if (IS_ERR(err_ptr)) { + err = PTR_ERR(err_ptr); + goto out; + } + } + + out: + mutex_unlock(&tc_mutex); + err: + return err; +} +module_init(stedma40_test_init); + +static void __exit stedma40_test_exit(void) +{ + DBG_TEST(printk(KERN_INFO "[%s]\n", __func__)); + + sted40_history_reset(); + + debugfs_remove_recursive(debugfs_dir); +} +module_exit(stedma40_test_exit); + + diff --git a/kernel/testcases/dma/user-space/Makefile b/kernel/testcases/dma/user-space/Makefile new file mode 100644 index 0000000..e950b1f --- /dev/null +++ b/kernel/testcases/dma/user-space/Makefile @@ -0,0 +1,26 @@ +ifeq ($(KERNELRELEASE),) +LTP_DIR = $(abspath ../../../../) +LTP_FRAMEWORK = $(LTP_DIR)/ltp_framework + +SCRIPTS=$(wildcard *.sh) + +CFLAGS+= -I$(LTP_FRAMEWORK)/include -I$(abspath ./include) +LOADLIBES+= -L$(LTP_FRAMEWORK)/lib -lltp + +TARGETS=dma +OBJS=dma.o + +all: $(TARGETS) + +$(TARGETS): $(TARGETS) $(OBJS) + +install: + @for i in $(TARGETS); do if [ -f $(DESTDIR)/opt/ltp/testcases/bin/$$i ]; then rm $(DESTDIR)/opt/ltp/testcases/bin/$$i; fi ; done + @for i in $(TARGETS); do install -D $$i $(DESTDIR)/opt/ltp/testcases/bin/$$i ; done + @for i in $(SCRIPTS); do if [ -f $(DESTDIR)/opt/ltp/testcases/bin/$$i ]; then rm $(DESTDIR)/opt/ltp/testcases/bin/$$i; fi ; done + @for i in $(SCRIPTS); do install -D $$i $(DESTDIR)/opt/ltp/testcases/bin/$$i ; done + +clean: + rm -f $(TARGETS) + rm -f $(OBJS) +endif diff --git a/kernel/testcases/dma/user-space/dma.c b/kernel/testcases/dma/user-space/dma.c new file mode 100644 index 0000000..f3dd062 --- /dev/null +++ b/kernel/testcases/dma/user-space/dma.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2010 ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + * + * Author: 2010, Martin Persson , + * Jonas Aaberg + */ + +#include "test.h" +#include "usctest.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + + + +/* Extern Global Variables */ +extern int Tst_count; /* counter for tst_xxx routines. */ +extern char *TESTDIR; /* temporary dir created by tst_tmpdir() */ + +/* Global Variables */ +char *TCID = "dma"; + +int test_cases[] = { + 22, 23, 24, 25, 1, 2, 3, 4, 6, 7, 8, + 21, 15, 16, 17, 18, 19, 20, 21, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, + + /* run long tests near the end */ + 26, 7, 32, 33, 5, 34, 27, 28, 29, + + /* + * The following fail: + * + * This due to hardware error V1, should be fixed in V2: + * 30, 31, 35, 51 + * + * These fail due to unknown reason: + * 9 + */ +}; + +/* total number of tests in this file. */ +int TST_TOTAL = sizeof(test_cases); + +static int dma_test(int id) +{ + int fd = 0, size, err = 0; + char fname[256], buff[256], answer[256]; + + sprintf(fname, "/sys/kernel/debug/ste_dma40_test/test_%d", id); + + fd = open(fname, O_RDONLY); + + if (fd < 0) { + err = -1; + goto _exit; + } + memset(buff, 0, 256); + size = read(fd, buff, 255); + if (size <= 0) { + err = -2; + goto _exit; + } + + sprintf(answer, "Finished test %d: OK\n", id); + if (size != strlen(answer)) { + printf("DMA testcase %d failed\n", id); + err = -3; + goto _exit; + } + + if (strncmp(buff, answer, strlen(answer))) { + printf("DMA testcase %d failed\n", id); + err = -4; + } + +_exit: + if (fd > 0) + close(fd); + + return err; +} + +static int n_opt; +static char *n_copt; +static int testnum; + +static option_t options[] = { + { "n:", &n_opt, &n_copt }, + { }, +}; + +int main(int argc, char **argv) +{ + + int lc; /* loop counter */ + char *msg; /* message returned from parse_opts */ + + /*************************************************************** + * parse standard options + ***************************************************************/ + if ((msg = parse_opts(argc, argv, options, NULL)) != (char *) NULL) { + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + tst_exit(); + } + + if (n_opt) { + testnum = atoi(n_copt); + TST_TOTAL = 1; + } + + system("modprobe stedma40_test"); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + + /*************************************************************** + * only perform functional verification if flag set (-f not given) + ***************************************************************/ + if (STD_FUNCTIONAL_TEST) { + + for (Tst_count = 0; Tst_count < TST_TOTAL;) { + int num; + + num = TST_TOTAL == 1 ? + testnum : test_cases[Tst_count]; + + TEST(dma_test(num)); + + if (TEST_RETURN == 0) + tst_resm(TPASS, "Functional test %d OK\n", num); + else + tst_resm(TFAIL, "Return value: %d. TCID: %s (%d) File: %s Line: %d. errno=%d : %s \n", + TEST_RETURN, TCID, num, __FILE__, __LINE__, + TEST_ERRNO, strerror(TEST_ERRNO)); + + } + } + } + + system("modprobe -r stedma40_test"); + + tst_exit(); + return 0; +} diff --git a/kernel/testcases/dma/user-space/dma_test_all.sh b/kernel/testcases/dma/user-space/dma_test_all.sh new file mode 100755 index 0000000..3a3aa94 --- /dev/null +++ b/kernel/testcases/dma/user-space/dma_test_all.sh @@ -0,0 +1,81 @@ +#/* +# * Copyright (C) ST-Ericsson SA 2010 +# * License Terms: GNU General Public License, version 2 +# */ + +# Runs all test for DMA +TEST_MODULE_NAME=stedma40_test +TEST_DIR=/sys/kernel/debug/ste_dma40_test +TEST_TMP_FILE=/.dma_run_test.sh + +echo "Loading test module $TEST_MODULE" +modprobe $TEST_MODULE_NAME +cd $TEST_DIR + +cat test_22 +cat test_23 +cat test_24 +cat test_25 + +cat test_1 +cat test_2 +cat test_3 +cat test_4 +cat test_6 +cat test_7 +cat test_8 + +# Testing dma using MMC +cat test_10 > $TEST_TMP_FILE +sh $TEST_TMP_FILE +cat test_11 > $TEST_TMP_FILE +sh $TEST_TMP_FILE +cat test_12 > $TEST_TMP_FILE +sh $TEST_TMP_FILE +cat test_13 > $TEST_TMP_FILE +sh $TEST_TMP_FILE + +# Endless test case, skip it here +# cat test_14 + +cat test_21 +cat test_15 +cat test_16 +cat test_17 +cat test_18 +cat test_19 +cat test_20 +cat test_21 +cat test_55 +cat test_56 +cat test_57 +cat test_58 +cat test_59 +cat test_60 +cat test_61 +cat test_62 +cat test_63 +cat test_64 + +cat test_26 +# run long tests near the end +cat test_7 +cat test_32 +cat test_33 +cat test_5 +cat test_34 +cat test_27 +cat test_28 +cat test_29 + +# The following fails: +# This due to hardware error V1, should be fixed in V2. +# cat test_30 +# cat test_31 +# cat test_35 +# cat test_51 +# These fail due to unknown reason. +# cat test_9 +# + +rmmod $TEST_MODULE_NAME diff --git a/ltp_framework/ChangeLog b/ltp_framework/ChangeLog new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/ltp_framework/ChangeLog @@ -0,0 +1 @@ + diff --git a/ltp_framework/IDcheck.sh b/ltp_framework/IDcheck.sh new file mode 100755 index 0000000..d453c91 --- /dev/null +++ b/ltp_framework/IDcheck.sh @@ -0,0 +1,189 @@ +#!/bin/sh +# +# Copyright (c) International Business Machines Corp., 2001 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +# the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# FILE : IDcheck.sh +# DESCRIPTION : checks for req'd users/groups and will create them if requested. +# HISTORY : see the cvs log +# + +# Prompt user if ids/groups should be created +echo "Checking for required user/group ids" +echo "" + +# Check ids and create if needed. +NO_NOBODY_ID=1 +NO_BIN_ID=1 +NO_DAEMON_ID=1 +NO_NOBODY_GRP=1 +NO_BIN_GRP=1 +NO_DAEMON_GRP=1 +NO_USERS_GRP=1 +NO_SYS_GRP=1 + +group="$DESTDIR/etc/group" +passwd="$DESTDIR/etc/passwd" + +# find entry. +fe() { + ID=$1 + FILE=$2 + [ -e "$FILE" ] || return $? + grep -q "^$ID:" "$FILE" +} + +prompt_for_create() { + if [ -z "$CREATE_ENTRIES" ] ; then + + if [ $NO_NOBODY_ID -ne 0 -o $NO_BIN_ID -ne 0 -o $NO_DAEMON_ID -ne 0 -o $NO_NOBODY_GRP -ne 0 -o $NO_BIN_GRP -ne 0 -o $NO_DAEMON_GRP -ne 0 -o $NO_USERS_GRP -ne 0 -o $NO_SYS_GRP -ne 0 ] ; then + echo -n "If any required user ids and/or groups are missing, would you like these created? [y/N]" + read ans + case "$ans" in + [Yy]*) CREATE_ENTRIES=1 ;; + *) CREATE_ENTRIES=0 ;; + esac + else + CREATE_ENTRIES=0 + fi + + fi +} + +if [ -z ${EUID} ] ; then + EUID=$(id -u) +fi + +for i in "$passwd" "$group"; do + if [ -e "$i" -a ! -r "$i" ] ; then + echo "$i not readable by uid $EUID" + exit 1 + fi +done + +fe bin "$passwd"; NO_BIN_ID=$? +fe daemon "$passwd"; NO_DAEMON_ID=$? +fe nobody "$passwd"; NO_NOBODY_ID=$? + +fe bin "$group"; NO_BIN_GRP=$? +fe daemon "$group"; NO_DAEMON_GRP=$? +fe nobody "$group" || fe nogroup "$group"; NO_NOBODY_GRP=$? +fe sys "$group"; NO_SYS_GRP=$? +fe users "$group"; NO_USERS_GRP=$? + +prompt_for_create + +debug_vals() { + +echo "Missing the following group / user entries:" +echo "Group file: $group" +echo "Password file: $passwd" +echo "nobody: $NO_NOBODY_ID" +echo "bin: $NO_BIN_ID" +echo "daemon: $NO_DAEMON_ID" +echo "nobody[/nogroup] grp: $NO_NOBODY_GRP" +echo "bin grp: $NO_BIN_GRP" +echo "daemon grp: $NO_DAEMON_GRP" +echo "sys grp: $NO_SYS_GRP" +echo "users grp: $NO_USERS_GRP" +echo "" + +} + +#debug_vals + +if [ $CREATE_ENTRIES -ne 0 ] ; then + if ! touch "$group" "$passwd" 2>/dev/null; then + echo "Failed to touch $group or $passwd" + exit 1 + fi +fi + +make_user_group() { + local name=$1 id=$2 no_id=$3 no_grp=$4 + + if [ $no_id -eq 0 -a $no_grp -eq 0 ] ; then + echo "'$name' user id and group found." + elif [ $CREATE_ENTRIES -ne 0 ] ; then + echo "Creating entries for $name" + + # Avoid chicken and egg issue with id(1) call + # made above and below. + if ! fe "$name" "$passwd" && [ $no_id -ne 0 ] ; then + echo "${name}:x:${id}:${id}:${name}::" >> "$passwd" + fi + if [ $no_grp -ne 0 ] ; then + echo "${name}:x:$(id -u ${name}):" >> "$group" + fi + fi +} +make_user_group nobody 65534 $NO_NOBODY_ID $NO_NOBODY_GRP +make_user_group bin 1 $NO_BIN_ID $NO_BIN_GRP +make_user_group daemon 2 $NO_DAEMON_ID $NO_DAEMON_GRP + +if [ $NO_USERS_GRP -eq 0 ] ; then + echo "Users group found." +elif [ $CREATE_ENTRIES -ne 0 ] ; then + echo 'users:x:100:' >> "$group" +fi + +if [ $NO_SYS_GRP -eq 0 ] ; then + echo "Sys group found." +elif [ $CREATE_ENTRIES -ne 0 ] ; then + echo 'sys:x:3:' >> "$group" +fi + +MISSING_ENTRY=0 + +# For entries that exist in both $group and $passwd. +for i in bin daemon; do + for file in "$group" "$passwd"; do + if ! fe "$i" "$file"; then + MISSING_ENTRY=1 + break + fi + done + if [ $MISSING_ENTRY -ne 0 ]; then + break + fi +done + +# nobody is a standard group on all distros, apart from debian based ones; +# let's account for the fact that they use the nogroup group instead. +if ! fe "nobody" "$passwd" || ! (fe "nogroup" "$group" || fe "nobody" "$group") +then + MISSING_ENTRY=1 +fi + +# For entries that only exist in $group. +for i in users sys; do + if ! fe "$i" "$group" ; then + MISSING_ENTRY=1 + fi +done + +if [ $MISSING_ENTRY -eq 0 ] ; then + echo "Required users/groups exist." + exit 0 +fi + +echo "" +echo "*****************************************" +echo "* Required users/groups do NOT exist!!! *" +echo "* *" +echo "* Some kernel/syscall tests will FAIL! *" +echo "*****************************************" +exit 1 diff --git a/ltp_framework/bin/ltp-pan b/ltp_framework/bin/ltp-pan new file mode 100755 index 0000000..18b604e Binary files /dev/null and b/ltp_framework/bin/ltp-pan differ diff --git a/ltp_framework/include/Makefile b/ltp_framework/include/Makefile new file mode 100644 index 0000000..243fd8a --- /dev/null +++ b/ltp_framework/include/Makefile @@ -0,0 +1,45 @@ +# +# include Makefile. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +top_srcdir ?= .. + +include $(top_srcdir)/include/mk/env_pre.mk + +INSTALL_DIR := $(includedir) + +INSTALL_MODE := 00644 + +INSTALL_TARGETS := *.h + +MAKE_TARGETS := + +.PHONY: ac-clean ac-distclean ac-maintainer-clean distclean maintainer-clean +distclean:: clean ac-distclean +maintainer-clean:: distclean ac-maintainer-clean +ac-clean ac-distclean:: + $(RM) -f config.h +ac-maintainer-clean:: + $(RM) -f config.h.in + +vpath %.h $(abs_srcdir) + +include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/ltp_framework/include/cleanup.c b/ltp_framework/include/cleanup.c new file mode 100644 index 0000000..31393fd --- /dev/null +++ b/ltp_framework/include/cleanup.c @@ -0,0 +1,45 @@ +/* + * Default cleanup logic because linux_syscall_numbers.h's need for cleanup + * and binutils bugs suck. + * + * Copyright (c) 2009 Cisco Systems, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + */ + +#ifndef __CLEANUP_C__ +#define __CLEANUP_C__ + +/* Did the user define a cleanup function? */ +#ifndef CLEANUP +# define USING_DUMMY_CLEANUP 1 +# define CLEANUP dummy_cleanup +#endif + +/* A freebie for defining the function prototype. */ +static void CLEANUP(void) __attribute__((unused)); + +#ifdef USING_DUMMY_CLEANUP +/* The stub function. Wewt.. */ +static void dummy_cleanup(void) { } +#endif + +#endif diff --git a/ltp_framework/include/compiler.h b/ltp_framework/include/compiler.h new file mode 100644 index 0000000..ec714fe --- /dev/null +++ b/ltp_framework/include/compiler.h @@ -0,0 +1,18 @@ +/* + * compiler.h: take care of fun compiler details here + * + * Licensed under the GPL-2 or later + */ + +#ifndef __LTP_COMPILER_H__ +#define __LTP_COMPILER_H__ + +#define LTP_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#define LTP_ATTRIBUTE_UNUSED __attribute__((unused)) +#define LTP_ATTRIBUTE_UNUSED_RESULT __attribute__((warn_unused_result)) + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) +#endif + +#endif /* __LTP_COMPILER_H__ */ diff --git a/ltp_framework/include/config.h b/ltp_framework/include/config.h new file mode 100644 index 0000000..174c6ad --- /dev/null +++ b/ltp_framework/include/config.h @@ -0,0 +1,293 @@ +/* include/config.h. Generated from config.h.in by configure. */ +/* include/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASM_LDT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASM_PTRACE_H 1 + +/* Define to 1 if you have the `daemon' function. */ +#define HAVE_DAEMON 1 + +/* Define to 1 if you have the declaration of `CLOCK_MONOTONIC_COARSE', and to + 0 if you don't. */ +#define HAVE_DECL_CLOCK_MONOTONIC_COARSE 1 + +/* Define to 1 if you have the declaration of `CLOCK_MONOTONIC_RAW', and to 0 + if you don't. */ +#define HAVE_DECL_CLOCK_MONOTONIC_RAW 1 + +/* Define to 1 if you have the declaration of `CLOCK_REALTIME_COARSE', and to + 0 if you don't. */ +#define HAVE_DECL_CLOCK_REALTIME_COARSE 1 + +/* Define to 1 if you have the declaration of `MADV_MERGEABLE', and to 0 if + you don't. */ +#define HAVE_DECL_MADV_MERGEABLE 1 + +/* Define to 1 if you have the declaration of `MPOL_BIND', and to 0 if you + don't. */ +#define HAVE_DECL_MPOL_BIND 0 + +/* Define to 1 if you have the declaration of `MPOL_DEFAULT', and to 0 if you + don't. */ +#define HAVE_DECL_MPOL_DEFAULT 0 + +/* Define to 1 if you have the declaration of `MPOL_F_ADDR', and to 0 if you + don't. */ +#define HAVE_DECL_MPOL_F_ADDR 0 + +/* Define to 1 if you have the declaration of `MPOL_F_MEMS_ALLOWED', and to 0 + if you don't. */ +#define HAVE_DECL_MPOL_F_MEMS_ALLOWED 0 + +/* Define to 1 if you have the declaration of `MPOL_F_NODE', and to 0 if you + don't. */ +#define HAVE_DECL_MPOL_F_NODE 0 + +/* Define to 1 if you have the declaration of `MPOL_INTERLEAVE', and to 0 if + you don't. */ +#define HAVE_DECL_MPOL_INTERLEAVE 0 + +/* Define to 1 if you have the declaration of `MPOL_PREFERRED', and to 0 if + you don't. */ +#define HAVE_DECL_MPOL_PREFERRED 0 + +/* Define to 1 if you have the declaration of `PR_CAPBSET_DROP', and to 0 if + you don't. */ +#define HAVE_DECL_PR_CAPBSET_DROP 1 + +/* Define to 1 if you have the declaration of `PR_CAPBSET_READ', and to 0 if + you don't. */ +#define HAVE_DECL_PR_CAPBSET_READ 1 + +/* Define to 1 if you have the declaration of `PTRACE_GETSIGINFO', and to 0 if + you don't. */ +#define HAVE_DECL_PTRACE_GETSIGINFO 1 + +/* Define to 1 if you have the declaration of `PTRACE_O_TRACEVFORKDONE', and + to 0 if you don't. */ +#define HAVE_DECL_PTRACE_O_TRACEVFORKDONE 1 + +/* Define to 1 if you have the declaration of `PTRACE_SETOPTIONS', and to 0 if + you don't. */ +#define HAVE_DECL_PTRACE_SETOPTIONS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DMAPI_H */ + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `io_set_eventfd' function. */ +/* #undef HAVE_IO_SET_EVENTFD */ + +/* Define to 1 if you have the libkeyutils development package and keyctl + syscall on your system */ +#define HAVE_KEYCTL_SYSCALL 0 + +/* Define to 1 if you have libacl installed. */ +/* #undef HAVE_LIBACL */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBAIO_H */ + +/* Define to 1 if you have libcap-2 installed. */ +/* #undef HAVE_LIBCAP */ + +/* Define to 1 if you have both SELinux libraries and headers. */ +/* #undef HAVE_LIBSELINUX_DEVEL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_GENETLINK_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_MEMPOLICY_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_MODULE_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_NETLINK_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_PTRACE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_SECUREBITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_SIGNALFD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_TASKSTATS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_TYPES_H 1 + +/* Define to 1 if you have MADV_MERGEABLE */ +#define HAVE_MADV_MERGEABLE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MM_H */ + +/* Define to 1 if you have the `modify_ldt' function. */ +/* #undef HAVE_MODIFY_LDT */ + +/* define to 1 if you have all constants required to use mbind tests */ +/* #undef HAVE_MPOL_CONSTANTS */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NUMAIF_H */ + +/* Define to 1 if you have the `numa_alloc_onnode' function. */ +/* #undef HAVE_NUMA_ALLOC_ONNODE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NUMA_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_SHA_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_PTHREAD_H 1 + +/* Define to 1 if you have quota v1 */ +/* #undef HAVE_QUOTAV1 */ + +/* Define to 1 if you have quota v2 */ +#define HAVE_QUOTAV2 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SELINUX_SELINUX_H */ + +/* Define to 1 if you have the `signalfd' function. */ +#define HAVE_SIGNALFD 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SIGNALFD_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if the system has the type `struct modify_ldt_ldt_s'. */ +/* #undef HAVE_STRUCT_MODIFY_LDT_LDT_S */ + +/* Define to 1 if the system has the type `struct pt_regs'. */ +#define HAVE_STRUCT_PT_REGS 1 + +/* Define to 1 if `sa_sigaction' is member of `struct sigaction'. */ +#define HAVE_STRUCT_SIGACTION_SA_SIGACTION 1 + +/* Define to 1 if `signo' is member of `struct signalfd_siginfo'. */ +/* #undef HAVE_STRUCT_SIGNALFD_SIGINFO_SIGNO */ + +/* Define to 1 if `ssi_signo' is member of `struct signalfd_siginfo'. */ +#define HAVE_STRUCT_SIGNALFD_SIGINFO_SSI_SIGNO 1 + +/* Define to 1 if `freepages_count' is member of `struct taskstats'. */ +#define HAVE_STRUCT_TASKSTATS_FREEPAGES_COUNT 1 + +/* Define to 1 if `nvcsw' is member of `struct taskstats'. */ +#define HAVE_STRUCT_TASKSTATS_NVCSW 1 + +/* Define to 1 if `read_bytes' is member of `struct taskstats'. */ +#define HAVE_STRUCT_TASKSTATS_READ_BYTES 1 + +/* Define to 1 if the system has the type `struct user_desc'. */ +/* #undef HAVE_STRUCT_USER_DESC */ + +/* Define to 1 if the system has the type `struct user_regs_struct'. */ +/* #undef HAVE_STRUCT_USER_REGS_STRUCT */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_ACL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_CAPABILITY_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_EPOLL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_INOTIFY_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_JFSDMAPI_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PRCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PTRACE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_REG_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SIGNALFD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unshare' function. */ +#define HAVE_UNSHARE 1 + +/* Define to 1 if you have the `vfork' function. */ +#define HAVE_VFORK 1 + +/* Name of package */ +#define PACKAGE "ltp" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "ltp-list@lists.sourceforge.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "ltp" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "ltp LTP_VERSION" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "ltp" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "LTP_VERSION" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Target is running Linux w/out an MMU */ +/* #undef UCLINUX */ + +/* Version number of package */ +#define VERSION "LTP_VERSION" + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +/* #undef YYTEXT_POINTER */ diff --git a/ltp_framework/include/config.h.default b/ltp_framework/include/config.h.default new file mode 100644 index 0000000..15ff210 --- /dev/null +++ b/ltp_framework/include/config.h.default @@ -0,0 +1,251 @@ +/* include/config.h.default. + A semi-sane set of defaults for more recent Linux platforms. Please tailor + to meet your needs. + */ + +/* Define to 1 if you have the new implementation of quotactl that only + requires sys/types.h and sys/quota.h */ +#define HAS_NEW_MINIMAL_QUOTACTL 1 + +/* Define to 1 if you have the RHEL ~4.6 version of quotactl, e.g. require + linux/quota.h instead of sys/quota.h */ +#undef HAS_RHEL46_QUOTACTL + +/* Define to 1 if you have the RHEL 4.8+ version of quotactl, e.g. require + sys/quota.h */ +#define HAS_RHEL48_QUOTACTL + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASM_LDT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ATTR_XATTR_H + +/* Define to 1 if you have the declaration of `CAP_BSET_DROP', and to 0 if you + don't. */ +#undef HAVE_DECL_CAP_BSET_DROP + +/* Define to 1 if you have the declaration of `CAP_BSET_READ', and to 0 if you + don't. */ +#undef HAVE_DECL_CAP_BSET_READ + +/* Define to 1 if you have the declaration of `cap_compare', and to 0 if you + don't. */ +#undef HAVE_DECL_CAP_COMPARE + +/* Define to 1 if you have the declaration of `cap_free', and to 0 if you + don't. */ +#undef HAVE_DECL_CAP_FREE + +/* Define to 1 if you have the declaration of `cap_from_text', and to 0 if you + don't. */ +#undef HAVE_DECL_CAP_FROM_TEXT + +/* Define to 1 if you have the declaration of `cap_get_proc', and to 0 if you + don't. */ +#undef HAVE_DECL_CAP_GET_PROC + +/* Define to 1 if you have the declaration of `cap_set_file', and to 0 if you + don't. */ +#undef HAVE_DECL_CAP_SET_FILE + +/* Define to 1 if you have the declaration of `cap_set_flag', and to 0 if you + don't. */ +#undef HAVE_DECL_CAP_SET_FLAG + +/* Define to 1 if you have the declaration of `cap_set_proc', and to 0 if you + don't. */ +#undef HAVE_DECL_CAP_SET_PROC + +/* Define to 1 if you have the declaration of `cap_to_text', and to 0 if you + don't. */ +#undef HAVE_DECL_CAP_TO_TEXT + +/* Define to 1 if you have the declaration of `PR_CAPBSET_READ', and to 0 if + you don't. */ +#undef HAVE_DECL_PR_CAPBSET_READ + +/* Define to 1 if you have the declaration of `PTRACE_GETSIGINFO', and to 0 if + you don't. */ +#define HAVE_DECL_PTRACE_GETSIGINFO 1 + +/* Define to 1 if you have the declaration of `PTRACE_O_TRACEVFORKDONE', and + to 0 if you don't. */ +#define HAVE_DECL_PTRACE_O_TRACEVFORKDONE 1 + +/* Define to 1 if you have the declaration of `PTRACE_SETOPTIONS', and to 0 if + you don't. */ +#undef HAVE_DECL_PTRACE_SETOPTIONS + +/* Define to 1 if you have the header file. */ +#undef HAVE_DMAPI_H + +/* Define to 1 if you have the header file. */ +#define HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `io_set_eventfd' function. */ +#undef HAVE_IO_SET_EVENTFD + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBAIO_H + +/* Define to 1 if you have both SELinux libraries and headers. */ +#undef HAVE_LIBSELINUX_DEVEL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_GENETLINK_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_MODULE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_NETLINK_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_PTRACE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_SIGNALFD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_TASKSTATS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MM_H + +/* Define to 1 if you have the `modify_ldt' function. */ +#undef HAVE_MODIFY_LDT + +/* 2.6 version of swapon/swapoff */ +#define HAVE_NEW_SWAPONOFF 1 + +/* Define to 1 if you have the `numa_alloc_onnode' function. */ +#undef HAVE_NUMA_ALLOC_ONNODE + +/* Define to 1 if you have the header file. */ +#undef HAVE_NUMA_H + +/* 2.4 version of swapon/swapoff */ +#undef HAVE_OLD_SWAPONOFF + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_SHA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SELINUX_SELINUX_H + +/* Define to 1 if you have the `signalfd' function. */ +#define HAVE_SIGNALFD 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNALFD_H 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if the system has the type `struct modify_ldt_ldt_s'. */ +#undef HAVE_STRUCT_MODIFY_LDT_LDT_S + +/* Define to 1 if `signo' is member of `struct signalfd_siginfo'. */ +#undef HAVE_STRUCT_SIGNALFD_SIGINFO_SIGNO + +/* Define to 1 if `ssi_signo' is member of `struct signalfd_siginfo'. */ +#undef HAVE_STRUCT_SIGNALFD_SIGINFO_SSI_SIGNO + +/* Define to 1 if `freepages_count' is member of `struct taskstats'. */ +#undef HAVE_STRUCT_TASKSTATS_FREEPAGES_COUNT + +/* Define to 1 if `nvcsw' is member of `struct taskstats'. */ +#undef HAVE_STRUCT_TASKSTATS_NVCSW + +/* Define to 1 if `read_bytes' is member of `struct taskstats'. */ +#undef HAVE_STRUCT_TASKSTATS_READ_BYTES + +/* Define to 1 if the system has the type `struct user_desc'. */ +#undef HAVE_STRUCT_USER_DESC + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_ACL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_CAPABILITY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_EPOLL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_INOTIFY_H 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_JFSDMAPI_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PRCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SIGNALFD_H + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unshare' function. */ +#undef HAVE_UNSHARE + +/* 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 version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#undef VERSION + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#undef YYTEXT_POINTER + +/* + * vim: syntax=c + */ diff --git a/ltp_framework/include/config.h.in b/ltp_framework/include/config.h.in new file mode 100644 index 0000000..690f43b --- /dev/null +++ b/ltp_framework/include/config.h.in @@ -0,0 +1,292 @@ +/* include/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASM_LDT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASM_PTRACE_H + +/* Define to 1 if you have the `daemon' function. */ +#undef HAVE_DAEMON + +/* Define to 1 if you have the declaration of `CLOCK_MONOTONIC_COARSE', and to + 0 if you don't. */ +#undef HAVE_DECL_CLOCK_MONOTONIC_COARSE + +/* Define to 1 if you have the declaration of `CLOCK_MONOTONIC_RAW', and to 0 + if you don't. */ +#undef HAVE_DECL_CLOCK_MONOTONIC_RAW + +/* Define to 1 if you have the declaration of `CLOCK_REALTIME_COARSE', and to + 0 if you don't. */ +#undef HAVE_DECL_CLOCK_REALTIME_COARSE + +/* Define to 1 if you have the declaration of `MADV_MERGEABLE', and to 0 if + you don't. */ +#undef HAVE_DECL_MADV_MERGEABLE + +/* Define to 1 if you have the declaration of `MPOL_BIND', and to 0 if you + don't. */ +#undef HAVE_DECL_MPOL_BIND + +/* Define to 1 if you have the declaration of `MPOL_DEFAULT', and to 0 if you + don't. */ +#undef HAVE_DECL_MPOL_DEFAULT + +/* Define to 1 if you have the declaration of `MPOL_F_ADDR', and to 0 if you + don't. */ +#undef HAVE_DECL_MPOL_F_ADDR + +/* Define to 1 if you have the declaration of `MPOL_F_MEMS_ALLOWED', and to 0 + if you don't. */ +#undef HAVE_DECL_MPOL_F_MEMS_ALLOWED + +/* Define to 1 if you have the declaration of `MPOL_F_NODE', and to 0 if you + don't. */ +#undef HAVE_DECL_MPOL_F_NODE + +/* Define to 1 if you have the declaration of `MPOL_INTERLEAVE', and to 0 if + you don't. */ +#undef HAVE_DECL_MPOL_INTERLEAVE + +/* Define to 1 if you have the declaration of `MPOL_PREFERRED', and to 0 if + you don't. */ +#undef HAVE_DECL_MPOL_PREFERRED + +/* Define to 1 if you have the declaration of `PR_CAPBSET_DROP', and to 0 if + you don't. */ +#undef HAVE_DECL_PR_CAPBSET_DROP + +/* Define to 1 if you have the declaration of `PR_CAPBSET_READ', and to 0 if + you don't. */ +#undef HAVE_DECL_PR_CAPBSET_READ + +/* Define to 1 if you have the declaration of `PTRACE_GETSIGINFO', and to 0 if + you don't. */ +#undef HAVE_DECL_PTRACE_GETSIGINFO + +/* Define to 1 if you have the declaration of `PTRACE_O_TRACEVFORKDONE', and + to 0 if you don't. */ +#undef HAVE_DECL_PTRACE_O_TRACEVFORKDONE + +/* Define to 1 if you have the declaration of `PTRACE_SETOPTIONS', and to 0 if + you don't. */ +#undef HAVE_DECL_PTRACE_SETOPTIONS + +/* Define to 1 if you have the header file. */ +#undef HAVE_DMAPI_H + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_IFADDRS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `io_set_eventfd' function. */ +#undef HAVE_IO_SET_EVENTFD + +/* Define to 1 if you have the libkeyutils development package and keyctl + syscall on your system */ +#undef HAVE_KEYCTL_SYSCALL + +/* Define to 1 if you have libacl installed. */ +#undef HAVE_LIBACL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBAIO_H + +/* Define to 1 if you have libcap-2 installed. */ +#undef HAVE_LIBCAP + +/* Define to 1 if you have both SELinux libraries and headers. */ +#undef HAVE_LIBSELINUX_DEVEL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_GENETLINK_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_MEMPOLICY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_MODULE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_NETLINK_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_PTRACE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_SECUREBITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_SIGNALFD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_TASKSTATS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_TYPES_H + +/* Define to 1 if you have MADV_MERGEABLE */ +#undef HAVE_MADV_MERGEABLE + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MM_H + +/* Define to 1 if you have the `modify_ldt' function. */ +#undef HAVE_MODIFY_LDT + +/* define to 1 if you have all constants required to use mbind tests */ +#undef HAVE_MPOL_CONSTANTS + +/* Define to 1 if you have the header file. */ +#undef HAVE_NUMAIF_H + +/* Define to 1 if you have the `numa_alloc_onnode' function. */ +#undef HAVE_NUMA_ALLOC_ONNODE + +/* Define to 1 if you have the header file. */ +#undef HAVE_NUMA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_SHA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have quota v1 */ +#undef HAVE_QUOTAV1 + +/* Define to 1 if you have quota v2 */ +#undef HAVE_QUOTAV2 + +/* Define to 1 if you have the header file. */ +#undef HAVE_SELINUX_SELINUX_H + +/* Define to 1 if you have the `signalfd' function. */ +#undef HAVE_SIGNALFD + +/* Define to 1 if you have the header file. */ +#undef HAVE_SIGNALFD_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 the system has the type `struct modify_ldt_ldt_s'. */ +#undef HAVE_STRUCT_MODIFY_LDT_LDT_S + +/* Define to 1 if the system has the type `struct pt_regs'. */ +#undef HAVE_STRUCT_PT_REGS + +/* Define to 1 if `sa_sigaction' is member of `struct sigaction'. */ +#undef HAVE_STRUCT_SIGACTION_SA_SIGACTION + +/* Define to 1 if `signo' is member of `struct signalfd_siginfo'. */ +#undef HAVE_STRUCT_SIGNALFD_SIGINFO_SIGNO + +/* Define to 1 if `ssi_signo' is member of `struct signalfd_siginfo'. */ +#undef HAVE_STRUCT_SIGNALFD_SIGINFO_SSI_SIGNO + +/* Define to 1 if `freepages_count' is member of `struct taskstats'. */ +#undef HAVE_STRUCT_TASKSTATS_FREEPAGES_COUNT + +/* Define to 1 if `nvcsw' is member of `struct taskstats'. */ +#undef HAVE_STRUCT_TASKSTATS_NVCSW + +/* Define to 1 if `read_bytes' is member of `struct taskstats'. */ +#undef HAVE_STRUCT_TASKSTATS_READ_BYTES + +/* Define to 1 if the system has the type `struct user_desc'. */ +#undef HAVE_STRUCT_USER_DESC + +/* Define to 1 if the system has the type `struct user_regs_struct'. */ +#undef HAVE_STRUCT_USER_REGS_STRUCT + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_ACL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_CAPABILITY_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_INOTIFY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_JFSDMAPI_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PRCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PTRACE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_REG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SIGNALFD_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_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `unshare' function. */ +#undef HAVE_UNSHARE + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* 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 version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Target is running Linux w/out an MMU */ +#undef UCLINUX + +/* Version number of package */ +#undef VERSION + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#undef YYTEXT_POINTER diff --git a/ltp_framework/include/dataascii.h b/ltp_framework/include/dataascii.h new file mode 100644 index 0000000..d08fe86 --- /dev/null +++ b/ltp_framework/include/dataascii.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +#ifndef _DATAASCII_H_ +#define _DATAASCII_H_ + +/*********************************************************************** + * int dataasciigen(listofchars, buffer, size, offset) + * + * This function fills buffer with ascii characters. + * The ascii characters are obtained from listofchars or the CHARS array + * if listofchars is NULL. + * Each char is selected by an index. The index is the remainder + * of count divided by the array size. + * This method allows more than one process to write to a location + * in a file without corrupting it for another process' point of view. + * + * The return value will be the number of character written in buffer + * (size). + * + ***********************************************************************/ +int dataasciigen(char *, char *, int, int); + +/*********************************************************************** + * int dataasciichk(listofchars, buffer, size, count, errmsg) + * + * This function checks the contents of a buffer produced by + * dataasciigen. + * + * return values: + * >= 0 : error at character count + * < 0 : no error + ***********************************************************************/ + +int dataasciichk(char *, char *, int, int, char**); + +#endif diff --git a/ltp_framework/include/databin.h b/ltp_framework/include/databin.h new file mode 100644 index 0000000..93c3863 --- /dev/null +++ b/ltp_framework/include/databin.h @@ -0,0 +1,44 @@ +#ifndef _DATABIN_H_ +#define _DATABIN_H_ + +/******************************************************************************* +* NAME +* databingen - fill a buffer with a data pattern +* +* SYNOPSIS +* (void) databingen(mode, buffer, bsize, offset) +* int mode; +* char *buffer; +* int bsize; +* int offset; +* +* DESCRIPTION +* datagen fills the buffer pointed to by 'buffer' with 'bsize' bytes +* of data of the form indicated by 'mode'. +* All modes (expect r -random) are file offset based. +* This allows more than process to do writing to the file without +* corrupting it if the same modes were used. +* They data modes to choose from, these are: +* +* 'a' - writes an alternating bit pattern (i.e. 0x5555555...) +* +* 'c' - writes a checkerboard pattern (i.e. 0xff00ff00ff00...) +* +* 'C' - writes counting pattern (i.e. 0 - 07, 0 - 07, ...); +* +* 'o' - writes all bits set (i.e. 0xffffffffffffff...) +* +* 'z' - writes all bits cleared (i.e. 0x000000000...); +* +* 'r' - writes random integers +* +* RETURN VALUE +* None +* +*******************************************************************************/ + +void databingen( int mode, char *buffer, int bsize, int offset ); + +int databinchk( int mode, char *buffer, int bsize, int offset, char **errmsg); + +#endif diff --git a/ltp_framework/include/file_lock.h b/ltp_framework/include/file_lock.h new file mode 100644 index 0000000..7586260 --- /dev/null +++ b/ltp_framework/include/file_lock.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +#ifndef _FILE_LOCK_H_ +#define _FILE_LOCK_H_ + +extern char Fl_syscall_str[128]; + +int file_lock( int , int, char ** ); +int record_lock( int , int , int , int , char ** ); + +#if defined(__sun) || defined(__hpux) +#define LOCK_NB 0x0001 +#define LOCK_UN 0x0002 +#define LOCK_EX 0x0004 +#define LOCK_SH 0x0008 +#endif +#endif /* _FILE_LOCK_H_ */ diff --git a/ltp_framework/include/forker.h b/ltp_framework/include/forker.h new file mode 100644 index 0000000..dfad625 --- /dev/null +++ b/ltp_framework/include/forker.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +#ifndef _FORKER_H_ +#define _FORKER_H_ + +#define FORKER_MAX_PIDS 4098 + +extern int Forker_pids[FORKER_MAX_PIDS]; /* holds pids of forked processes */ +extern int Forker_npids; /* number of entries in Forker_pids */ + +/* + * This function will fork and the parent will exit zero and + * the child will return. This will orphan the returning process + * putting it in the background. + */ +int background( char * ); + +/* + * Forker will fork ncopies-1 copies of self. + * + * arg 1: Number of copies of the process to be running after return. + * This value minus one is the number of forks performed. + * arg 2: mode: 0 - all children are first generation descendents. + * 1 - each subsequent child is a descendent of another + * descendent, resulting in only one direct descendent of the + * parent and each other child is a child of another child in + * relation to the parent. + * arg 3: prefix: string to preceed any error messages. A value of NULL + * results in no error messages on failure. + * returns: returns to parent the number of children forked. + */ +int forker( int , int , char * ); + +#endif /* _FORKER_H_ */ diff --git a/ltp_framework/include/libtestsuite.h b/ltp_framework/include/libtestsuite.h new file mode 100644 index 0000000..0668961 --- /dev/null +++ b/ltp_framework/include/libtestsuite.h @@ -0,0 +1,20 @@ +/* The following functions are used to synchronize father and sons processes. + * + * create_sync_pipes: create pipes used for the synchronization. Must be done + * by father process before a fork. + * + * wait_son_startup: wait a son process to reach the "notify_startup" function. + * + * notify_startup: notify the father process a son has started its execution. + */ +#include +#include +#include + +/* fifo_name is used to create named pipe. NULL means anonymous pipe. */ +#define PIPE_NAME NULL +int sync_pipe_create( int fd[], const char *pipe_name); +int sync_pipe_close(int fd[], const char *pipe_name); +int sync_pipe_wait( int fd[]); +int sync_pipe_notify( int fd[]); + diff --git a/ltp_framework/include/ltp_signal.h b/ltp_framework/include/ltp_signal.h new file mode 100644 index 0000000..1ac6f70 --- /dev/null +++ b/ltp_framework/include/ltp_signal.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2009 Cisco Systems, Inc. All Rights Reserved. + * Copyright (c) 2009 FUJITSU LIMITED. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Author: Liu Bo + * Author: Garrett Cooper + * + */ + +#ifndef __LTP_SIGNAL_H +#define __LTP_SIGNAL_H + +#include +#include +#include +#include "config.h" + +#define SIGSETSIZE (_NSIG / 8) + +#ifdef LTP_RT_SIG_TEST + +#ifdef __x86_64__ + +/* + * From asm/signal.h -- this value isn't exported anywhere outside of glibc and + * asm/signal.h and is only required for the rt_sig* function family because + * sigaction(2), et all, appends this if necessary to + * (struct sigaction).sa_flags. HEH. + * + * I do #undef though, just in case... + * + * Also, from .../arch/x86/kernel/signal.c:448 for v2.6.30 (something or + * other): + * + * x86-64 should always use SA_RESTORER. + * + * -- thus SA_RESTORER must always be defined along with + * (struct sigaction).sa_restorer for this architecture. + */ +#undef SA_RESTORER +#define HAVE_SA_RESTORER +#define SA_RESTORER 0x04000000 + +struct kernel_sigaction { + __sighandler_t k_sa_handler; + unsigned long sa_flags; + void (*sa_restorer) (void); + sigset_t sa_mask; +}; + +void (*restore_rt) (void); + +inline void +handler_h (int signal) +{ + return; +} + +/* Setup an initial signal handler for signal number = sig for x86_64. */ +inline int +sig_initial(int sig) +{ + int ret_code = -1; + struct sigaction act, oact; + + act.sa_handler = handler_h; + /* Clear out the signal set. */ + if (sigemptyset(&act.sa_mask) < 0) { + /* Add the signal to the mask set. */ + } else if (sigaddset(&act.sa_mask, sig) < 0) { + /* Set act.sa_restorer via syscall(2) */ + } else if (sigaction(sig, &act, &oact) < 0) { + /* Copy oact.sa_restorer via syscall(2) */ + } else if (sigaction(sig, &act, &oact) < 0) { + /* And voila -- we just tricked the kernel into giving us our + * restorer function! */ + } else { + restore_rt = oact.sa_restorer; + ret_code = 0; + } + + return ret_code; + +} + +#endif /* __x86_64__ */ + +#endif /* LTP_RT_SIG_TEST */ + +#endif diff --git a/ltp_framework/include/mk/automake.mk b/ltp_framework/include/mk/automake.mk new file mode 100644 index 0000000..e5a4fe0 --- /dev/null +++ b/ltp_framework/include/mk/automake.mk @@ -0,0 +1,117 @@ +# +# Autotools include Makefile. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +# Override these variables to use non-system available tools. +ACLOCAL ?= aclocal +AUTOCONF ?= autoconf +AUTOHEADER ?= autoheader +AUTOMAKE ?= automake + +AUTOCONFED_SUBDIRS = \ + testcases/realtime + +# We want to run this every single time to ensure that all of the prereq files +# are there. +.PHONY: testcases/realtime/configure +testcases/realtime/configure: + $(MAKE) -C $(@D) autotools + +.PHONY: autotools +autotools: aclocal autoconf autoheader automake $(addsuffix /configure,$(AUTOCONFED_SUBDIRS)) + +.PHONY: aclocal +aclocal: aclocal.m4 + +aclocal.m4: $(wildcard m4/*.m4) m4/ltp-version.m4 + $(ACLOCAL) -I m4 + +.PHONY: autoconf +autoconf: configure + +configure: configure.ac aclocal.m4 + $(AUTOCONF) + +.PHONY: autoheader +autoheader: configure.ac $(wildcard m4/*.m4) m4/ltp-version.m4 aclocal.m4 + $(AUTOHEADER) + +include: + mkdir -p "$@" + +m4/ltp-version.m4: ChangeLog + sed -n '1{s:LTP-:m4_define([LTP_VERSION],[:;s:$$:]):;p;q}' $< > $@ + +.PHONY: automake +AUTOMAKE_FILES := config.guess config.sub install-sh missing stamp-h1 +automake: aclocal $(AUTOMAKE_FILES) +$(AUTOMAKE_FILES): m4/Makefile.in +m4/Makefile.in: m4/Makefile.am aclocal.m4 + $(AUTOMAKE) -c -a + +.PHONY: ac-clean ac-distclean ac-maintainer-clean +ac-clean:: + $(RM) -rf autom4te.cache + $(RM) -f config.log config.status + $(RM) -f include/config.h include/stamp-h1 + $(RM) -f m4/Makefile m4/ltp-version.m4 + for d in $(AUTOCONFED_SUBDIRS); do \ + $(MAKE) -C "$(top_srcdir)/$$d" $@; \ + done + +ac-distclean:: ac-clean +ac-maintainer-clean:: ac-distclean + for d in $(AUTOCONFED_SUBDIRS); do \ + $(MAKE) -C "$(top_srcdir)/$$d" $@; \ + done + $(RM) -f aclocal.m4 configure $(AUTOMAKE_FILES) m4/Makefile.in + $(RM) -f include/*config.h.in + +# Don't include config.h, or make will (rightfully) whine about overriding +# rules. +# +# This list should match the files in configure.ac. +# +AUTOGENERATED_FILES = \ + include/mk/config.mk \ + include/mk/features.mk \ + lib/ltp.pc \ + m4/Makefile \ + ltp-devel.spec \ + execltp \ + README.ltp-devel + +distclean:: %: clean ac-distclean + for d in $(AUTOCONFED_SUBDIRS); do \ + $(MAKE) -C "$(top_srcdir)/$$d" $@; \ + done + $(RM) -f $(AUTOGENERATED_FILES) + +maintainer-clean:: distclean ac-maintainer-clean + +$(AUTOGENERATED_FILES): $(top_builddir)/config.status + $(SHELL) $^ + +# This variable is automatically changed from help to all once someone has +# run configure, or the equivalent steps manually, as described in INSTALL. +$(abs_top_builddir)/include/mk/config.mk \ +$(abs_top_builddir)/include/mk/features.mk: + $(MAKE) -C $(top_srcdir) help; false diff --git a/ltp_framework/include/mk/config.mk b/ltp_framework/include/mk/config.mk new file mode 100644 index 0000000..de7a353 --- /dev/null +++ b/ltp_framework/include/mk/config.mk @@ -0,0 +1,82 @@ +# +# config.mk.in. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +# See this page for more info about LEX*: +# http://www.gnu.org/software/hello/manual/autoconf/Particular-Programs.html + +# Application specifying variables. You should never have to change these. +AR := arm-linux-gnueabi-ar +CC := arm-linux-gnueabi-gcc +LEX := : +RANLIB := arm-linux-gnueabi-ranlib +STRIP := arm-linux-gnueabi-strip +YACC := yacc + +# XXX: I'm lazy... but if someone has a working javac, they should have a +# working jar on their systems. +JAR := jar +JAVAC := @JAVAC@ + +AIO_LIBS := +CAP_LIBS := +ACL_LIBS := +CRYPTO_LIBS := +LEXLIB := +NUMA_CPPFLAGS := +NUMA_LIBS := +SELINUX_LIBS := + +prefix := /opt/ltp + +datarootdir := ${prefix}/share +includedir := ${prefix}/include +exec_prefix := ${prefix} +bindir := ${exec_prefix}/bin +libdir := ${exec_prefix}/lib +mandir := ${datarootdir}/man + +RPMBUILD ?= rpmbuild + +CPPFLAGS := +CFLAGS := -g -O2 +LDLIBS := +LDFLAGS := + +DEBUG_CFLAGS ?= -g +DEBUG_CXXFLAGS ?= $(DEBUG_CFLAGS) + +# Please see README.mk-devel about -fstrict-aliasing. +OPT_CFLAGS ?= -O2 -fno-strict-aliasing -pipe +OPT_CXXFLAGS ?= $(OPT_CFLAGS) + +WCFLAGS ?= -Wall +WCXXFLAGS ?= $(WCFLAGS) + +LDFLAGS += $(WLDFLAGS) +CFLAGS += $(DEBUG_CFLAGS) $(OPT_CFLAGS) $(WCFLAGS) +CXXFLAGS += $(DEBUG_CXXFLAGS) $(OPT_CXXFLAGS) $(WCXXFLAGS) + +ifeq ($(strip $(prefix)),) +$(error you are using $$(prefix) incorrectly -- set it to $(abs_top_srcdir) if you want to build in the source tree) +endif + +export datarootdir includedir libdir mandir prefix diff --git a/ltp_framework/include/mk/config.mk.default b/ltp_framework/include/mk/config.mk.default new file mode 100644 index 0000000..8248071 --- /dev/null +++ b/ltp_framework/include/mk/config.mk.default @@ -0,0 +1,76 @@ +# +# config.mk.in. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +# See this page for more info about LEX*: +# http://www.gnu.org/software/hello/manual/autoconf/Particular-Programs.html + +# Application specifying variables. You should never have to change these. +AR := ar +CC := gcc +LEX := flex +RANLIB := ranlib +STRIP := strip +YACC := bison -y + +#JAR := jar +#JAVAC := javac + +#AIO_LIBS := -laio +#CAP_LIBS := -lcap +#ACL_LIBS := -lacl +#CRYPTO_LIBS := -lcrypto +#LEXLIB := -lfl +#NUMA_CPPFLAGS := -DNUMA_VERSION1_COMPATIBILITY +#NUMA_LIBS := -lnuma +#SELINUX_LIBS := -lselinux + +prefix := /opt/ltp + +datarootdir := ${prefix}/share +includedir := ${prefix}/include +exec_prefix := ${prefix} +bindir := ${exec_prefix}/bin +libdir := ${exec_prefix}/lib +mandir := ${datarootdir}/man + +RPMBUILD ?= rpmbuild + +CPPFLAGS := +CFLAGS := -g -O2 +LDLIBS := +LDFLAGS := + +DEBUG_CFLAGS ?= -g +DEBUG_CXXFLAGS ?= $(DEBUG_CFLAGS) + +# Please see README.mk-devel about -fstrict-aliasing. +OPT_CFLAGS ?= -O2 -fno-strict-aliasing -pipe +OPT_CXXFLAGS ?= $(OPT_CFLAGS) + +WCFLAGS ?= -Wall +WCXXFLAGS ?= $(WCFLAGS) + +LDFLAGS += $(WLDFLAGS) +CFLAGS += $(DEBUG_CFLAGS) $(OPT_CFLAGS) $(WCFLAGS) +CXXFLAGS += $(DEBUG_CXXFLAGS) $(OPT_CXXFLAGS) $(WCXXFLAGS) + +export datarootdir includedir libdir mandir prefix diff --git a/ltp_framework/include/mk/config.mk.in b/ltp_framework/include/mk/config.mk.in new file mode 100644 index 0000000..b835c86 --- /dev/null +++ b/ltp_framework/include/mk/config.mk.in @@ -0,0 +1,82 @@ +# +# config.mk.in. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +# See this page for more info about LEX*: +# http://www.gnu.org/software/hello/manual/autoconf/Particular-Programs.html + +# Application specifying variables. You should never have to change these. +AR := @AR@ +CC := @CC@ +LEX := @LEX@ +RANLIB := @RANLIB@ +STRIP := @STRIP@ +YACC := @YACC@ + +# XXX: I'm lazy... but if someone has a working javac, they should have a +# working jar on their systems. +JAR := jar +JAVAC := @JAVAC@ + +AIO_LIBS := @AIO_LIBS@ +CAP_LIBS := @CAP_LIBS@ +ACL_LIBS := @ACL_LIBS@ +CRYPTO_LIBS := @CRYPTO_LIBS@ +LEXLIB := @LEXLIB@ +NUMA_CPPFLAGS := @NUMA_CPPFLAGS@ +NUMA_LIBS := @NUMA_LIBS@ +SELINUX_LIBS := @SELINUX_LIBS@ + +prefix := @prefix@ + +datarootdir := @datarootdir@ +includedir := @includedir@ +exec_prefix := @exec_prefix@ +bindir := @bindir@ +libdir := @libdir@ +mandir := @mandir@ + +RPMBUILD ?= rpmbuild + +CPPFLAGS := @CPPFLAGS@ +CFLAGS := @CFLAGS@ +LDLIBS := @LIBS@ +LDFLAGS := @LDFLAGS@ + +DEBUG_CFLAGS ?= -g +DEBUG_CXXFLAGS ?= $(DEBUG_CFLAGS) + +# Please see README.mk-devel about -fstrict-aliasing. +OPT_CFLAGS ?= -O2 -fno-strict-aliasing -pipe +OPT_CXXFLAGS ?= $(OPT_CFLAGS) + +WCFLAGS ?= -Wall +WCXXFLAGS ?= $(WCFLAGS) + +LDFLAGS += $(WLDFLAGS) +CFLAGS += $(DEBUG_CFLAGS) $(OPT_CFLAGS) $(WCFLAGS) +CXXFLAGS += $(DEBUG_CXXFLAGS) $(OPT_CXXFLAGS) $(WCXXFLAGS) + +ifeq ($(strip $(prefix)),) +$(error you are using $$(prefix) incorrectly -- set it to $(abs_top_srcdir) if you want to build in the source tree) +endif + +export datarootdir includedir libdir mandir prefix diff --git a/ltp_framework/include/mk/env_post.mk b/ltp_framework/include/mk/env_post.mk new file mode 100644 index 0000000..ebaee1f --- /dev/null +++ b/ltp_framework/include/mk/env_post.mk @@ -0,0 +1,104 @@ +# +# Environment post-setup Makefile. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +ENV_PRE_LOADED ?= $(error You must load env_pre.mk before including this file) + +include $(top_srcdir)/include/mk/functions.mk + +ifndef ENV_POST_LOADED +ENV_PRE_LOADED = 1 + +# Default source search path. Modify as necessary, but I would call that +# poor software design if you need more than one search directory, and +# would suggest creating a general purpose static library to that end. +vpath %.c $(abs_srcdir) + +# For config.h, et all. +CPPFLAGS += -I$(top_srcdir)/include -I$(top_builddir)/include + +LDFLAGS += -L$(top_builddir)/lib + +ifeq ($(UCLINUX),1) +CPPFLAGS += -D__UCLIBC__ -DUCLINUX +endif + +MAKE_TARGETS ?= $(notdir $(patsubst %.c,%,$(wildcard $(abs_srcdir)/*.c))) + +MAKE_TARGETS := $(filter-out $(FILTER_OUT_MAKE_TARGETS),$(MAKE_TARGETS)) + +CLEAN_TARGETS += $(MAKE_TARGETS) *.o *.pyc + +# Majority of the files end up in testcases/bin... +INSTALL_DIR ?= testcases/bin + +ifneq ($(filter-out install,$(MAKECMDGOALS)),$(MAKECMDGOALS)) + +ifeq ($(strip $(INSTALL_DIR)),) +INSTALL_DIR := $(error You must define INSTALL_DIR before including this file) +endif + +ifneq ($(strip $(prefix)),) +# Value specified by INSTALL_DIR isn't an absolute path, so let's tack on $(prefix). +ifneq ($(patsubst /%,,$(INSTALL_DIR)),) +INSTALL_DIR := $(prefix)/$(INSTALL_DIR) +endif + +# Glob any possible expressions, but make sure to zap the $(abs_srcdir) +# reference at the start of the filename instead of using $(notdir), so that +# way we don't accidentally nuke the relative path from $(abs_srcdir) that +# may have been set in the Makefile. +INSTALL_TARGETS := $(wildcard $(addprefix $(abs_srcdir)/,$(INSTALL_TARGETS))) +INSTALL_TARGETS := $(patsubst $(abs_srcdir)/%,%,$(INSTALL_TARGETS)) + +# The large majority of the files that we install are going to be apps and +# scripts, so let's chmod them like that. +INSTALL_MODE ?= 00775 + +ifdef MAKE_3_80_COMPAT + +INSTALL_PATH := $(call MAKE_3_80_abspath,$(DESTDIR)/$(INSTALL_DIR)) + +INSTALL_TARGETS_ABS := $(call MAKE_3_80_abspath,$(addprefix $(INSTALL_PATH)/,$(INSTALL_TARGETS))) +MAKE_TARGETS_ABS := $(call MAKE_3_80_abspath,$(addprefix $(INSTALL_PATH)/,$(MAKE_TARGETS))) + +INSTALL_FILES := $(INSTALL_TARGETS_ABS) $(MAKE_TARGETS_ABS) + +$(INSTALL_TARGETS_ABS): + test -d "$(@D)" || mkdir -p "$(@D)" + install -m $(INSTALL_MODE) "$(abs_srcdir)/$(subst $(INSTALL_PATH)/,,$@)" "$@" + +$(MAKE_TARGETS_ABS): + test -d "$(@D)" || mkdir -p "$(@D)" + install -m $(INSTALL_MODE) "$(abs_builddir)/$(subst $(INSTALL_PATH)/,,$@)" "$@" +else +$(abspath $(addprefix $(DESTDIR)/$(INSTALL_DIR)/,$(sort $(dir $(INSTALL_TARGETS) $(MAKE_TARGETS))))): + mkdir -p "$@" +$(foreach install_target,$(INSTALL_TARGETS),$(eval $(call generate_install_rule,$(install_target),$(abs_srcdir),$(INSTALL_DIR)))) +$(foreach make_target,$(MAKE_TARGETS),$(eval $(call generate_install_rule,$(make_target),$(abs_builddir),$(INSTALL_DIR)))) +endif + +else # else ! $(filter-out install,$(MAKECMDGOALS)),$(MAKECMDGOALS) +$(error You must define $$(prefix) before executing install) +endif # END $(filter-out install,$(MAKECMDGOALS)),$(MAKECMDGOALS) +endif + +endif diff --git a/ltp_framework/include/mk/env_pre.mk b/ltp_framework/include/mk/env_pre.mk new file mode 100644 index 0000000..f1584a8 --- /dev/null +++ b/ltp_framework/include/mk/env_pre.mk @@ -0,0 +1,144 @@ +# +# Make pre-include environment Makefile. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, September 2009 +# +# This Makefile must be included first. NO IF'S, AND'S, OR BUT'S. +# +# This sets the stage for all operations required within Makefiles. +# + +ifndef ENV_PRE_LOADED +ENV_PRE_LOADED = 1 + +# "out-of-build-tree" build. +BUILD_TREE_BUILDDIR_INSTALL := 1 +# "in-srcdir" build / install. +BUILD_TREE_SRCDIR_INSTALL := 2 +# "in-srcdir" build, non-srcdir install. +BUILD_TREE_NONSRCDIR_INSTALL := 3 +# configure not run. +BUILD_TREE_UNCONFIGURED := 4 + +ifndef MAKE_VERSION_CHECK +export MAKE_VERSION_CHECK = 1 +ifneq ($(firstword $(sort 3.80 $(MAKE_VERSION))),3.80) +$(error Your version of make $(MAKE_VERSION) is too old. Upgrade to at least 3.80; 3.81+ is preferred) +else +ifneq ($(filter 3.80%,$(MAKE_VERSION)),) +export MAKE_3_80_COMPAT := 1 +endif # make 3.80? +endif # At least make 3.80? +endif # MAKE_VERSION_CHECK + +# Get the absolute path for the source directory. +top_srcdir ?= $(error You must define top_srcdir before including this file) + +include $(top_srcdir)/include/mk/functions.mk + +# Where's the root source directory? +ifdef MAKE_3_80_COMPAT +abs_top_srcdir := $(call MAKE_3_80_abspath,$(top_srcdir)) +else +abs_top_srcdir := $(abspath $(top_srcdir)) +endif + +# +# Where's the root object directory? +# +# Just in case it's not specified, set it to the top srcdir (because the user +# must not have wanted out of build tree support)... +# +top_builddir ?= $(top_srcdir) + +# We need the absolute path... +ifdef MAKE_3_80_COMPAT +abs_top_builddir := $(call MAKE_3_80_abspath,$(top_builddir)) +else +abs_top_builddir := $(abspath $(top_builddir)) +endif + +# Where's the root object directory? +builddir := . + +abs_builddir := $(CURDIR) + +cwd_rel_from_top := $(subst $(abs_top_builddir),,$(abs_builddir)) + +# Where's the source located at? Squish all of the / away by using abspath... +ifdef MAKE_3_80_COMPAT +abs_srcdir := $(call MAKE_3_80_abspath,$(abs_top_srcdir)/$(cwd_rel_from_top)) +else +abs_srcdir := $(abspath $(abs_top_srcdir)/$(cwd_rel_from_top)) +endif + +srcdir := $(strip $(subst $(abs_top_srcdir)/,,$(abs_srcdir))) + +ifeq ($(srcdir),) +srcdir := . +endif + +# autotools, *clean, and help don't require config.mk, features.mk, etc... +ifeq ($(filter autotools %clean .gitignore gitignore.% help,$(MAKECMDGOALS)),) + +include $(abs_top_builddir)/include/mk/config.mk +include $(abs_top_builddir)/include/mk/features.mk + +# START out-of-build-tree check. +ifneq ($(abs_builddir),$(abs_srcdir)) +BUILD_TREE_STATE := $(BUILD_TREE_BUILDDIR_INSTALL) +else +# Else, not out of build tree.. + +# START srcdir build-tree install checks +ifeq ($(strip $(DESTDIR)$(prefix)),) +BUILD_TREE_STATE := $(BUILD_TREE_SRCDIR_INSTALL) +else # Empty $(DESTDIR)$(prefix) +ifeq ($(abs_top_srcdir),$(prefix)) +BUILD_TREE_STATE := $(BUILD_TREE_SRCDIR_INSTALL) +endif +# END srcdir build-tree install checks +endif +# END out-of-build-tree check. +endif + +# Is the build-tree configured yet? +ifeq ($(BUILD_TREE_STATE),) +ifneq ($(wildcard $(abs_top_builddir)/include/mk/config.mk),) +BUILD_TREE_STATE := $(BUILD_TREE_NONSRCDIR_INSTALL) +endif +endif + +ifeq ($(MAKE_3_80_COMPAT),1) +# Trick make 3.80 into thinking that the default goal is all. +.PHONY: default +default: all +else +.DEFAULT_GOAL := all +endif + +endif # END autotools, *clean... + +BUILD_TREE_STATE ?= $(BUILD_TREE_UNCONFIGURED) + +# We can piece together where we're located in the source and object trees with +# just these two vars and $(CURDIR). +export abs_top_srcdir abs_top_builddir BUILD_TREE_STATE + +endif diff --git a/ltp_framework/include/mk/features.mk b/ltp_framework/include/mk/features.mk new file mode 100644 index 0000000..d06a80a --- /dev/null +++ b/ltp_framework/include/mk/features.mk @@ -0,0 +1,55 @@ +# +# features.mk.in - feature tuning include Makefile. +# +# Copyright (C) 2010, Linux Test Project. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, October 2010 +# + +# Path to capset program +CAPSET := + +# Tools enable knobs +WITH_EXPECT := no + +WITH_PERL := no + +WITH_PYTHON := no + +# Features knobs + +# Is securebits[.h], et all support available? +HAVE_SECUREBITS := yes + +# Test suite knobs + +# Enable testcases/kernel/power_management's compile and install? +ifeq ($(UCLINUX),1) +WITH_POWER_MANAGEMENT_TESTSUITE := no +else +WITH_POWER_MANAGEMENT_TESTSUITE := no +endif + +# Enable testcases/open_posix_testsuite's compile and install? +WITH_OPEN_POSIX_TESTSUITE := no + +# Enable testcases/realtime's compile and install? +ifeq ($(UCLINUX),1) +WITH_REALTIME_TESTSUITE := no +else +WITH_REALTIME_TESTSUITE := no +endif diff --git a/ltp_framework/include/mk/features.mk.default b/ltp_framework/include/mk/features.mk.default new file mode 100644 index 0000000..53ea30c --- /dev/null +++ b/ltp_framework/include/mk/features.mk.default @@ -0,0 +1,55 @@ +# +# features.mk.default - feature tuning include Makefile. +# +# Copyright (C) 2010, Linux Test Project. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, October 2010 +# + +# Path to capset program +CAPSET := + +# Tools enable knobs +WITH_EXPECT := no + +WITH_PERL := no + +WITH_PYTHON := no + +# Features knobs + +# Is securebits[.h], et all support available? +HAVE_SECUREBITS := no + +# Test suite knobs + +# Enable testcases/kernel/power_management's compile and install? +ifeq ($(UCLINUX),1) +WITH_POWER_MANAGEMENT_TESTSUITE := no +else +WITH_POWER_MANAGEMENT_TESTSUITE := +endif + +# Enable testcases/open_posix_testsuite's compile and install? +WITH_OPEN_POSIX_TESTSUITE := no + +# Enable testcases/realtime's compile and install? +ifeq ($(UCLINUX),1) +WITH_REALTIME_TESTSUITE := no +else +WITH_REALTIME_TESTSUITE := no +endif diff --git a/ltp_framework/include/mk/features.mk.in b/ltp_framework/include/mk/features.mk.in new file mode 100644 index 0000000..3472159 --- /dev/null +++ b/ltp_framework/include/mk/features.mk.in @@ -0,0 +1,55 @@ +# +# features.mk.in - feature tuning include Makefile. +# +# Copyright (C) 2010, Linux Test Project. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, October 2010 +# + +# Path to capset program +CAPSET := @CAPSET@ + +# Tools enable knobs +WITH_EXPECT := @WITH_EXPECT@ + +WITH_PERL := @WITH_PERL@ + +WITH_PYTHON := @WITH_PYTHON@ + +# Features knobs + +# Is securebits[.h], et all support available? +HAVE_SECUREBITS := @HAVE_SECUREBITS@ + +# Test suite knobs + +# Enable testcases/kernel/power_management's compile and install? +ifeq ($(UCLINUX),1) +WITH_POWER_MANAGEMENT_TESTSUITE := no +else +WITH_POWER_MANAGEMENT_TESTSUITE := @WITH_POWER_MANAGEMENT_TESTSUITE@ +endif + +# Enable testcases/open_posix_testsuite's compile and install? +WITH_OPEN_POSIX_TESTSUITE := @WITH_OPEN_POSIX_TESTSUITE@ + +# Enable testcases/realtime's compile and install? +ifeq ($(UCLINUX),1) +WITH_REALTIME_TESTSUITE := no +else +WITH_REALTIME_TESTSUITE := @WITH_REALTIME_TESTSUITE@ +endif diff --git a/ltp_framework/include/mk/functions.mk b/ltp_framework/include/mk/functions.mk new file mode 100644 index 0000000..fc58737 --- /dev/null +++ b/ltp_framework/include/mk/functions.mk @@ -0,0 +1,76 @@ +# +# A Makefile with a collection of reusable functions. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +SQUOTE := ' + +# ' # to keep colorized editors from going nuts + +MAKE_3_80_realpath = $(shell $(top_srcdir)/scripts/realpath.sh '$(subst $(SQUOTE),\\$(SQUOTE),$(1))') + +MAKE_3_80_abspath = $(shell $(top_srcdir)/scripts/abspath.sh '$(subst $(SQUOTE),\\$(SQUOTE),$(1))') + +# +# NOTE (garrcoop): +# +# The following functions are (sometimes) split into 3.80 and 3.81+ +# counterparts, and not conditionalized inside of the define(s) to work around +# an issue with how make 3.80 evaluates defines. +# +# SO DO NOT INTERNALIZE CONDITIONALS IN DEFINES OR YOU WILL BREAK MAKE 3.80! +# + +# +# Generate an install rule which also creates the install directory if needed +# to avoid unnecessary bourne shell based for-loops and install errors, as well +# as adhoc install rules. +# +# 1 -> Target basename. +# 2 -> Source directory. +# 3 -> Destination directory. +# +ifdef MAKE_3_80_COMPAT +define generate_install_rule + +INSTALL_FILES += $$(call MAKE_3_80_abspath,$$(DESTDIR)/$(3)/$(1)) + +$$(call MAKE_3_80_abspath,$$(DESTDIR)/$(3)/$(1)): \ + $$(call MAKE_3_80_abspath,$$(dir $$(DESTDIR)/$(3)/$(1))) + install -m $$(INSTALL_MODE) "$(2)/$(1)" "$$@" +endef +else # not MAKE_3_80_COMPAT +define generate_install_rule + +INSTALL_FILES += $$(abspath $$(DESTDIR)/$(3)/$(1)) + +$$(abspath $$(DESTDIR)/$(3)/$(1)): \ + $$(abspath $$(dir $$(DESTDIR)/$(3)/$(1))) + install -m $$(INSTALL_MODE) "$(2)/$(1)" "$$@" +endef +endif # END MAKE_3_80_COMPAT + +# +# Set SUBDIRS to the subdirectories where Makefiles were found. +# +define get_make_dirs +SUBDIRS ?= $$(subst $$(abs_srcdir)/,,$$(patsubst %/Makefile,%,$$(wildcard $$(abs_srcdir)/*/Makefile))) +SUBDIRS := $$(filter-out $$(FILTER_OUT_DIRS),$$(SUBDIRS)) +endef diff --git a/ltp_framework/include/mk/generic_leaf_target.inc b/ltp_framework/include/mk/generic_leaf_target.inc new file mode 100644 index 0000000..a88586f --- /dev/null +++ b/ltp_framework/include/mk/generic_leaf_target.inc @@ -0,0 +1,106 @@ +# +# Generic leaf rules include Makefile. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +# +# generic_leaf_target +# +# Generate a set of basic targets (all, clean, install) for a leaf directory +# (no subdirectories). +# +# $(MAKE_DEPS) : What should we execute beforehand as a +# dependency of $(MAKE_TARGETS)? +# +# $(INSTALL_FILES) -> install +# +# Helpful variables are: +# +# $(MAKE_TARGETS) : What to execute as direct dependencies of +# all. +# 1. Defaults to the basename of the targets +# produced by the %.c -> % implicit pattern +# rules, e.g. the MAKE_TARGET in a directory +# like the following: +# +# $$ ls /bar +# foo.c +# +# Would be `foo'. Similarly, the following +# dir structure: +# +# $$ ls /bar +# foo.c zanzibar.c +# +# Would be `foo zanzibar'. +# +# 2. If you define MAKE_TARGETS as an empty +# string, this will override the defaults. +# I did this to avoid providing too much +# rope to hang one's self in the event of +# unwanted behavior. +# +# $(CLEAN_TARGETS) : What targets should be cleaned (must be +# real files). This will automatically append +# adds the .o suffix to all files referenced +# by $(MAKE_TARGETS)) to CLEAN_TARGETS, if +# MAKE_TARGETS wasn't defined (see +# $(MAKE_TARGETS)). +# $(INSTALL_MODE) : What mode should we using when calling +# install(1)? +# +# Also, if you wish to change the installation directory, from the set default +# (testcases/bin) you must do something like either one of the following items: +# +# Method A: +# +# INSTALL_DIR := /path/to/installdir/from/$(DESTDIR)/$(prefix) +# +# e.g. if I wanted to install my binaries in testcases/bin, I would do: +# +# INSTALL_DIR := testcases/bin +# +# in my calling Makefile. +# +# Or Method B: +# +# INSTALL_DIR := /path/to/installdir/from/$(DESTDIR) +# +# e.g. if I wanted to install my binaries in $(libdir) (which may not exist +# outside of $(prefix) right now, but could in the future), I could do the +# following: +# +# INSTALL_DIR := $(libdir) +# + +.PHONY: all clean install + +$(MAKE_TARGETS): | $(MAKE_DEPS) + +all: $(MAKE_TARGETS) + +clean:: $(CLEAN_DEPS) + -$(RM) -f $(CLEAN_TARGETS) + +$(INSTALL_FILES): | $(INSTALL_DEPS) + +install: $(INSTALL_FILES) + +# vim: syntax=make diff --git a/ltp_framework/include/mk/generic_leaf_target.mk b/ltp_framework/include/mk/generic_leaf_target.mk new file mode 100644 index 0000000..cb6db5e --- /dev/null +++ b/ltp_framework/include/mk/generic_leaf_target.mk @@ -0,0 +1,24 @@ +# +# Generic leaf include Makefile. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +include $(top_srcdir)/include/mk/env_post.mk +include $(top_srcdir)/include/mk/generic_leaf_target.inc diff --git a/ltp_framework/include/mk/generic_trunk_target.inc b/ltp_framework/include/mk/generic_trunk_target.inc new file mode 100644 index 0000000..86d654c --- /dev/null +++ b/ltp_framework/include/mk/generic_trunk_target.inc @@ -0,0 +1,97 @@ +# +# Generic trunk rules include Makefile. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +# +# generic_trunk_target +# +# Generate a set of recursive targets to apply over a trunk directory (has +# directories) -- optionally with a set of trunk-based files. +# +# All variables in this canned define are essentially the same as +# generic_leaf_target, with the exception that the install flow for local +# targets is: +# +# $(INSTALL_FILES) -> trunk-install -> install (recursive) +# +# All recursive targets are traverse SUBDIRS as defined by the user, or if +# undefined, defaults to any subdirectories where Makefile's are contained +# within. +# +# generic_trunk_target specific variables are: +# +# RECURSIVE_TARGETS : a list of targets to apply over an entire +# directory tree. This defaults to +# `all install'. +# +# See generic_leaf_target, generic_target_env_setup, and get_make_dirs for +# more details and design notes. +# + +include $(top_srcdir)/include/mk/functions.mk + +RECURSIVE_TARGETS ?= all install + +$(eval $(get_make_dirs)) + +.PHONY: $(RECURSIVE_TARGETS) $(addprefix trunk-,$(RECURSIVE_TARGETS)) + +$(SUBDIRS): %: + mkdir -m 00755 -p "$@" + +$(MAKE_TARGETS): | $(MAKE_DEPS) + +trunk-all: $(MAKE_TARGETS) + +trunk-clean:: | $(SUBDIRS) + $(if $(strip $(CLEAN_TARGETS)),$(RM) -f $(CLEAN_TARGETS)) + +$(INSTALL_FILES): | $(INSTALL_DEPS) + +trunk-install: $(INSTALL_FILES) + +# Avoid creating duplicate .PHONY references to all, clean, and install. IIRC, +# I've seen some indeterministic behavior when one does this in the past with +# GNU Make... +.PHONY: $(filter-out $(RECURSIVE_TARGETS),all clean install) +all: trunk-all + +clean:: trunk-clean + @set -e; for dir in $(SUBDIRS); do \ + $(MAKE) -C "$$dir" -f "$(abs_srcdir)/$$dir/Makefile" $@; \ + done +ifneq ($(abs_builddir),$(abs_srcdir)) + $(RM) -Rf $(SUBDIRS) +endif + +install: trunk-install + +# Print out CURDIR to check for a recursion issue. +ifeq ($(strip $(SUBDIRS)),) + $(warning CURDIR is: $(CURDIR)) +else +$(RECURSIVE_TARGETS): %: | $(SUBDIRS) + @set -e; for dir in $(SUBDIRS); do \ + $(MAKE) -C $$dir -f "$(abs_srcdir)/$$dir/Makefile" $@; \ + done +endif + +# vim: syntax=make diff --git a/ltp_framework/include/mk/generic_trunk_target.mk b/ltp_framework/include/mk/generic_trunk_target.mk new file mode 100644 index 0000000..f480ef6 --- /dev/null +++ b/ltp_framework/include/mk/generic_trunk_target.mk @@ -0,0 +1,24 @@ +# +# Generic trunk include Makefile. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +include $(top_srcdir)/include/mk/env_post.mk +include $(top_srcdir)/include/mk/generic_trunk_target.inc diff --git a/ltp_framework/include/mk/gitignore.mk b/ltp_framework/include/mk/gitignore.mk new file mode 100644 index 0000000..b9932fb --- /dev/null +++ b/ltp_framework/include/mk/gitignore.mk @@ -0,0 +1,51 @@ +# +# gitignore generation include Makefile. +# +# Copyright (C) 2011, Linux Test Project. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, January 2011 +# + +CLEAN_TARGETS+= gitignore_clean + +BEFORE:= .gitignore-before + +AFTER:= .gitignore-after + +IGNORE_DIR_EXPR:= egrep -v "^$$(echo "$(AUTOCONFED_SUBDIRS)" | tr " " "|")" + +# NOTE: The underscore is used in place of a dash to avoid implicit rule +# evaluation in top-level Makefile. +.PHONY: gitignore_clean +gitignore_clean: + $(RM) -f $(BEFORE) $(AFTER) + +$(BEFORE): + $(MAKE) distclean + $(MAKE) ac-maintainer-clean + find . | $(IGNORE_DIR_EXPR) > $@ + +$(AFTER): + $(MAKE) autotools + ./configure --prefix=/dev/null + $(MAKE) all + find . | $(IGNORE_DIR_EXPR) > $@ + # Set everything in autoconf land back to a sane state. + $(MAKE) distclean + +.gitignore: | $(BEFORE) $(AFTER) + diff -u $(BEFORE) $(AFTER) | grep '^+' | sed -e 's,^\+,,g' > $@ diff --git a/ltp_framework/include/mk/lib.mk b/ltp_framework/include/mk/lib.mk new file mode 100644 index 0000000..bc0c45d --- /dev/null +++ b/ltp_framework/include/mk/lib.mk @@ -0,0 +1,64 @@ +# +# library include Makefile. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +# Makefile to include for libraries. + +include $(top_srcdir)/include/mk/env_pre.mk + +INSTALL_DIR := $(libdir) + +# An extension of generic_leaf_target, strictly for libraries. +.PHONY: install_headers + +ifndef LIB +$(error You must define LIB when including this Makefile) +endif + +install_headers: $(addprefix $(DESTDIR)/$(includedir)/,$(notdir $(HEADER_FILES))) + +INSTALL_MODE ?= 00664 + +MAKE_TARGETS := $(LIB) + +LIBSRCS ?= $(wildcard $(abs_srcdir)/*.c) + +ifdef MAKE_3_80_COMPAT +LIBSRCS := $(call MAKE_3_80_abspath,$(LIBSRCS)) +else +LIBSRCS := $(abspath $(LIBSRCS)) +endif + +LIBSRCS := $(subst $(abs_srcdir)/,,$(wildcard $(LIBSRCS))) + +LIBSRCS := $(filter-out $(FILTER_OUT_LIBSRCS),$(LIBSRCS)) + +LIBOBJS := $(LIBSRCS:.c=.o) + +$(LIB): $(notdir $(LIBOBJS)) + if [ -z "$(strip $^)" ] ; then \ + echo "Cowardly refusing to create empty archive"; \ + exit 1; \ + fi + $(if $(AR),$(AR),ar) -rc "$@" $^ + $(if $(RANLIB),$(RANLIB),ranlib) "$@" + +include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/ltp_framework/include/mk/man.mk b/ltp_framework/include/mk/man.mk new file mode 100644 index 0000000..f0b4525 --- /dev/null +++ b/ltp_framework/include/mk/man.mk @@ -0,0 +1,37 @@ +# +# Manpage include Makefile. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +ifeq ($(strip $(MANPREFIX)),) +$(error $$(MANPREFIX) not defined) +endif + +include $(top_srcdir)/include/mk/env_pre.mk + +INSTALL_DIR := $(mandir)/man$(MANPREFIX) + +INSTALL_MODE := 00644 + +INSTALL_TARGETS ?= *.$(MANPREFIX) + +MAKE_TARGETS := + +include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/ltp_framework/include/mk/testcases.mk b/ltp_framework/include/mk/testcases.mk new file mode 100644 index 0000000..ea26d4f --- /dev/null +++ b/ltp_framework/include/mk/testcases.mk @@ -0,0 +1,55 @@ +# +# testcases include Makefile. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +include $(top_srcdir)/include/mk/env_pre.mk +include $(top_srcdir)/include/mk/functions.mk + +APICMDS_DIR := $(abs_top_builddir)/tools/apicmds + +TKI_DIR := testcases/kernel/include + +LSN_H := $(abs_top_builddir)/$(TKI_DIR)/linux_syscall_numbers.h + +LIBLTP_DIR := $(abs_top_builddir)/lib + +LIBLTP := $(LIBLTP_DIR)/libltp.a + +$(APICMDS_DIR)/tst_kvercmp: $(APICMDS_DIR) + $(MAKE) -C "$^" -f "$(abs_top_srcdir)/tools/apicmds/Makefile" all + +$(LIBLTP): $(LIBLTP_DIR) + $(MAKE) -C "$^" -f "$(abs_top_srcdir)/lib/Makefile" all + +$(LSN_H): $(abs_top_builddir)/$(TKI_DIR) + $(MAKE) -C "$^" -f "$(abs_top_srcdir)/$(TKI_DIR)/Makefile" all + +MAKE_DEPS := $(LIBLTP) $(LSN_H) + +# For linux_syscall_numbers.h +CPPFLAGS += -I$(abs_top_builddir)/$(TKI_DIR) + +INSTALL_DIR := testcases/bin + +LDLIBS += -lltp + +$(APICMDS_DIR) $(LIBLTP_DIR) $(abs_top_builddir)/$(TKI_DIR): %: + mkdir -p "$@" diff --git a/ltp_framework/include/open_flags.h b/ltp_framework/include/open_flags.h new file mode 100644 index 0000000..966d684 --- /dev/null +++ b/ltp_framework/include/open_flags.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +#ifndef _OPEN_FLAGS_H_ +#define _OPEN_FLAGS_H_ + +/*********************************************************************** + * This function attempts to convert open flag bits into human readable + * symbols (i.e. O_TRUNC). If there are more than one symbol, + * the string will be placed as a separator between symbols. + * Commonly used separators would be a comma "," or pipe "|". + * If is one and not all bits can be converted to + * symbols, the "UNKNOWN" symbol will be added to return string. + * + * Return Value + * openflags2symbols will return the indentified symbols. + * If no symbols are recognized the return value will be a empty + * string or the "UNKNOWN" symbol. + * + * Limitations + * Currently (05/96) all known symbols are coded into openflags2symbols. + * If new open flags are added this code will have to updated + * to know about them or they will not be recognized. + * + * The Open_symbols must be large enough to hold all possible symbols + * for a given system. + * + ***********************************************************************/ +char *openflags2symbols( int, char *, int ); + +/*********************************************************************** + * This function will take a string of comma separated open flags symbols + * and translate them into an open flag bitmask. + * If any symbol is not valid, -1 is returned. On this error condition + * the badname pointer is updated if not NULL. badname will point + * to the beginning location of where the invalid symbol was found. + * string will be returned unchanged. + * + * A signal received while parsing string could cause the string to + * contain a NULL character in the middle of it. + * + ***********************************************************************/ +int parse_open_flags( char *, char ** ); + +#endif diff --git a/ltp_framework/include/pattern.h b/ltp_framework/include/pattern.h new file mode 100644 index 0000000..29c75d3 --- /dev/null +++ b/ltp_framework/include/pattern.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +#ifndef _PATTERN_H_ +#define _PATTERN_H_ + +/* + * pattern_check(buf, buflen, pat, patlen, patshift) + * + * Check a buffer of length buflen against repeated occurrances of + * a pattern whose length is patlen. Patshift can be used to rotate + * the pattern by patshift bytes to the left. + * + * Patshift may be greater than patlen, the pattern will be rotated by + * (patshift % patshift) bytes. + * + * pattern_check returns -1 if the buffer does not contain repeated + * occurrances of the indicated pattern (shifted by patshift). + * + * The algorithm used to check the buffer relies on the fact that buf is + * supposed to be repeated copies of pattern. The basic algorithm is + * to validate the first patlen bytes of buf against the pat argument + * passed in - then validate the next patlen bytes against the 1st patlen + * bytes - the next (2*patlen) bytes against the 1st (2*pathen) bytes, and + * so on. This algorithm only works when the assumption of a buffer full + * of repeated copies of a pattern holds, and gives MUCH better results + * then walking the buffer byte by byte. + * + * Performance wise, It appears to be about 5% slower than doing a straight + * memcmp of 2 buffers, but the big win is that it does not require a + * 2nd comparison buffer, only the pattern. + */ +int pattern_check( char * , int , char * , int , int ); + +/* + * pattern_fill(buf, buflen, pat, patlen, patshift) + * + * Fill a buffer of length buflen with repeated occurrances of + * a pattern whose length is patlen. Patshift can be used to rotate + * the pattern by patshift bytes to the left. + * + * Patshift may be greater than patlen, the pattern will be rotated by + * (patshift % patlen) bytes. + * + * If buflen is not a multiple of patlen, a partial pattern will be written + * in the last part of the buffer. This implies that a buffer which is + * shorter than the pattern length will receive only a partial pattern ... + * + * pattern_fill always returns 0 - no validation of arguments is done. + * + * The algorithm used to fill the buffer relies on the fact that buf is + * supposed to be repeated copies of pattern. The basic algorithm is + * to fill the first patlen bytes of buf with the pat argument + * passed in - then copy the next patlen bytes with the 1st patlen + * bytes - the next (2*patlen) bytes with the 1st (2*pathen) bytes, and + * so on. This algorithm only works when the assumption of a buffer full + * of repeated copies of a pattern holds, and gives MUCH better results + * then filling the buffer 1 byte at a time. + */ +int pattern_fill( char * , int , char * , int , int ); + +#endif diff --git a/ltp_framework/include/random_range.h b/ltp_framework/include/random_range.h new file mode 100644 index 0000000..c8c4858 --- /dev/null +++ b/ltp_framework/include/random_range.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +#ifndef _RANDOM_RANGE_H_ +#define _RANDOM_RANGE_H_ + +int parse_ranges ( char *, int, int, int, int (*)(), char **, char ** ); +int range_min ( char *, int ); +int range_max ( char *, int ); +int range_mult ( char *, int ); +long random_range ( int, int, int, char ** ); +long random_rangel ( long, long, long, char ** ); +long long random_rangell ( long long, long long, long long, char ** ); +void random_range_seed( long ); +long random_bit ( long ); + +#endif diff --git a/ltp_framework/include/rmobj.h b/ltp_framework/include/rmobj.h new file mode 100644 index 0000000..4808ca2 --- /dev/null +++ b/ltp_framework/include/rmobj.h @@ -0,0 +1,12 @@ +#ifndef _RMOBJ_H_ +#define _RMOBJ_H_ + +/* + * rmobj() - Remove the specified object. If the specified object is a + * directory, recursively remove everything inside of it. If + * there are any problems, set errmsg (if it is not NULL) and + * return -1. Otherwise return 0. + */ +int rmobj( char *object , char **errmesg ); + +#endif diff --git a/ltp_framework/include/safe_macros.h b/ltp_framework/include/safe_macros.h new file mode 100644 index 0000000..3753b7f --- /dev/null +++ b/ltp_framework/include/safe_macros.h @@ -0,0 +1,139 @@ +/* + * Safe macros for commonly used syscalls to reduce code duplication in LTP + * testcases, and to ensure all errors are caught in said testcases as + * gracefully as possible. + * + * Also satiates some versions of gcc/glibc when the warn_unused_result + * attribute is applied to the function call. + * + * Licensed under the GPLv2. + */ + +#ifndef __TEST_H__ +#error "you must include test.h before this file" +#else + +#ifndef __SAFE_MACROS_H__ +#define __SAFE_MACROS_H__ + +#include +#include +#include +#include +#include +#include + +char* safe_basename(const char *file, const int lineno, + void (*cleanup_fn)(void), char *path); +#define SAFE_BASENAME(cleanup_fn, path) \ + safe_basename(__FILE__, __LINE__, (cleanup_fn), (path)) + +int safe_chdir(const char *file, const int lineno, + void (*cleanup_fn)(void), const char *path); +#define SAFE_CHDIR(cleanup_fn, path) \ + safe_chdir(__FILE__, __LINE__, (cleanup_fn), (path)) + +int safe_close(const char *file, const int lineno, + void (*cleanup_fn)(void), int fildes); +#define SAFE_CLOSE(cleanup_fn, fildes) \ + safe_close(__FILE__, __LINE__, (cleanup_fn), (fildes)) + +int safe_creat(const char *file, const int lineno, + void (*cleanup_fn)(void), char *pathname, mode_t mode); +#define SAFE_CREAT(cleanup_fn, pathname, mode) \ + safe_creat(__FILE__, __LINE__, cleanup_fn, (pathname), (mode)) + +char* safe_dirname(const char *file, const int lineno, + void (*cleanup_fn)(void), char *path); +#define SAFE_DIRNAME(cleanup_fn, path) \ + safe_dirname(__FILE__, __LINE__, (cleanup_fn), (path)) + +char* safe_getcwd(const char *file, const int lineno, + void (*cleanup_fn)(void), char *buf, size_t size); +#define SAFE_GETCWD(cleanup_fn, buf, size) \ + safe_getcwd(__FILE__, __LINE__, (cleanup_fn), (buf), (size)) + +struct passwd* safe_getpwnam(const char *file, const int lineno, + void (*cleanup_fn)(void), const char *name); +#define SAFE_GETPWNAM(cleanup_fn, name) \ + safe_getpwnam(__FILE__, __LINE__, cleanup_fn, (name)) + +int safe_getrusage(const char *file, const int lineno, + void (*cleanup_fn)(void), int who, struct rusage *usage); +#define SAFE_GETRUSAGE(cleanup_fn, who, usage) \ + safe_getrusage(__FILE__, __LINE__, (cleanup_fn), (who), (usage)) + +void* safe_malloc(const char *file, const int lineno, + void (*cleanup_fn)(void), size_t size); +#define SAFE_MALLOC(cleanup_fn, size) \ + safe_malloc(__FILE__, __LINE__, (cleanup_fn), (size)) + +int safe_mkdir(const char *file, const int lineno, + void (*cleanup_fn)(void), const char *pathname, mode_t mode); +#define SAFE_MKDIR(cleanup_fn, pathname, mode) \ + safe_mkdir(__FILE__, __LINE__, (cleanup_fn), (pathname), (mode)) + +void* safe_mmap(const char *file, const int lineno, + void (*cleanup_fn)(void), void *addr, size_t length, int prot, + int flags, int fd, off_t offset); +#define SAFE_MMAP(cleanup_fn, addr, length, prot, flags, fd, offset) \ + safe_mmap(__FILE__, __LINE__, (cleanup_fn), (addr), (length), (prot), \ + (flags), (fd), (offset)) + +int safe_munmap(const char *file, const int lineno, + void (*cleanup_fn)(void), void *addr, size_t length); +#define SAFE_MUNMAP(cleanup_fn, addr, length) \ + safe_munmap(__FILE__, __LINE__, (cleanup_fn), (addr), (length)) + +int safe_open(const char *file, const int lineno, + void (*cleanup_fn)(void), const char *pathname, int oflags, ...); +#define SAFE_OPEN(cleanup_fn, pathname, oflags, ...) \ + safe_open(__FILE__, __LINE__, (cleanup_fn), (pathname), (oflags), \ + ##__VA_ARGS__) + +int safe_pipe(const char *file, const int lineno, + void (*cleanup_fn)(void), int fildes[2]); +#define SAFE_PIPE(cleanup_fn, fildes) \ + safe_pipe(__FILE__, __LINE__, cleanup_fn, (fildes)) + +ssize_t safe_read(const char *file, const int lineno, + void (*cleanup_fn)(void), char len_strict, int fildes, void *buf, + size_t nbyte); +#define SAFE_READ(cleanup_fn, len_strict, fildes, buf, nbyte) \ + safe_read(__FILE__, __LINE__, cleanup_fn, (len_strict), (fildes), \ + (buf), (nbyte)) + +int safe_setegid(const char *file, const int lineno, + void (*cleanup_fn)(void), gid_t egid); +#define SAFE_SETEGID(cleanup_fn, egid) \ + safe_setegid(__FILE__, __LINE__, cleanup_fn, (egid)) + +int safe_seteuid(const char *file, const int lineno, + void (*cleanup_fn)(void), uid_t euid); +#define SAFE_SETEUID(cleanup_fn, euid) \ + safe_seteuid(__FILE__, __LINE__, cleanup_fn, (euid)) + +int safe_setgid(const char *file, const int lineno, + void (*cleanup_fn)(void), gid_t gid); +#define SAFE_SETGID(cleanup_fn, gid) \ + safe_setgid(__FILE__, __LINE__, cleanup_fn, (gid)) + +int safe_setuid(const char *file, const int lineno, + void (*cleanup_fn)(void), uid_t uid); +#define SAFE_SETUID(cleanup_fn, uid) \ + safe_setuid(__FILE__, __LINE__, cleanup_fn, (uid)) + +int safe_unlink(const char *file, const int lineno, + void (*cleanup_fn)(void), const char *pathname); +#define SAFE_UNLINK(cleanup_fn, pathname) \ + safe_unlink(__FILE__, __LINE__, cleanup_fn, (pathname)) + +ssize_t safe_write(const char *file, const int lineno, + void (cleanup_fn)(void), char len_strict, int fildes, + const void *buf, size_t nbyte); +#define SAFE_WRITE(cleanup_fn, len_strict, fildes, buf, nbyte) \ + safe_write(__FILE__, __LINE__, cleanup_fn, (len_strict), (fildes), \ + (buf), (nbyte)) + +#endif +#endif diff --git a/ltp_framework/include/search_path.h b/ltp_framework/include/search_path.h new file mode 100644 index 0000000..c81d42c --- /dev/null +++ b/ltp_framework/include/search_path.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ + +/* $Id: search_path.h,v 1.2 2009/07/20 10:59:32 vapier Exp $ */ + + +int search_path(char *cmd, char *res_path, int access_mode, int fullpath); diff --git a/ltp_framework/include/stamp-h1 b/ltp_framework/include/stamp-h1 new file mode 100644 index 0000000..b330768 --- /dev/null +++ b/ltp_framework/include/stamp-h1 @@ -0,0 +1 @@ +timestamp for include/config.h diff --git a/ltp_framework/include/str_to_bytes.h b/ltp_framework/include/str_to_bytes.h new file mode 100644 index 0000000..977a6b1 --- /dev/null +++ b/ltp_framework/include/str_to_bytes.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +#ifndef _STR_TO_BYTES_ +#define _STR_TO_BYTES_ + +int str_to_bytes ( char * ); +long str_to_lbytes ( char * ); +long long str_to_llbytes( char * ); + +#endif diff --git a/ltp_framework/include/string_to_tokens.h b/ltp_framework/include/string_to_tokens.h new file mode 100644 index 0000000..75c7d24 --- /dev/null +++ b/ltp_framework/include/string_to_tokens.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +#ifndef _STRING_TO_TOKENS_H_ +#define _STRING_TO_TOKENS_H_ + +/* + * string_to_tokens() + * + * This function parses the string 'arg_string', placing pointers to + * the 'separator' separated tokens into the elements of 'arg_array'. + * The array is terminated with a null pointer. + * + * NOTE: This function uses strtok() to parse 'arg_string', and thus + * physically alters 'arg_string' by placing null characters where the + * separators originally were. + */ +int string_to_tokens(char *, char **, int, char *); + +#endif diff --git a/ltp_framework/include/swaponoff.h b/ltp_framework/include/swaponoff.h new file mode 100644 index 0000000..e3eae3f --- /dev/null +++ b/ltp_framework/include/swaponoff.h @@ -0,0 +1,18 @@ + +#ifndef __SWAP_ON_OFF_H_ +#define __SWAP_ON_OFF_H_ + +/* + * Read swapon(2) / swapoff(2) for a full history lesson behind the value of + * MAX_SWAPFILES. + */ +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) +#define MAX_SWAPFILES 30 +#elif LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 10) +#define MAX_SWAPFILES 32 +#else +#define MAX_SWAPFILES 8 +#endif + +#endif diff --git a/ltp_framework/include/system_specific_hugepages_info.h b/ltp_framework/include/system_specific_hugepages_info.h new file mode 100644 index 0000000..f5e3c46 --- /dev/null +++ b/ltp_framework/include/system_specific_hugepages_info.h @@ -0,0 +1,30 @@ +/* + * + * Copyright (c) International Business Machines Corp., 2009 + * + * 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 + */ + +#ifndef _SYS_SPECIFIC_HUGEPAGES_INFO_H_ +#define _SYS_SPECIFIC_HUGEPAGES_INFO_H_ + +/*Returns Total No. of available Hugepages in the system from /proc/meminfo*/ +int get_no_of_hugepages(void); +/*Returns No. of Hugepages_Free from /proc/meminfo*/ +int get_no_of_free_hugepages(void); +/*Returns Hugepages Size from /proc/meminfo*/ +int hugepages_size(void); + +#endif diff --git a/ltp_framework/include/system_specific_process_info.h b/ltp_framework/include/system_specific_process_info.h new file mode 100644 index 0000000..956d90f --- /dev/null +++ b/ltp_framework/include/system_specific_process_info.h @@ -0,0 +1,29 @@ +/* + * + * Copyright (c) International Business Machines Corp., 2009 + * + * 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 + */ + +#ifndef _SYS_SPECIFIC_PROCESS_INFO_H_ +#define _SYS_SPECIFIC_PROCESS_INFO_H_ + +/* Returns max pid count obtained from reading /proc/sys/kernel/pid_max */ +int get_max_pids(void); + +/* Returns number of free pids */ +int get_free_pids(void); + +#endif diff --git a/ltp_framework/include/test.h b/ltp_framework/include/test.h new file mode 100644 index 0000000..033fdbc --- /dev/null +++ b/ltp_framework/include/test.h @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2009 Cyril Hrubis chrubis@suse.cz + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ + +/* $Id: test.h,v 1.26 2010/01/10 22:27:15 yaberauneya Exp $ */ + +#ifndef __TEST_H__ +#define __TEST_H__ + +#include +#include +#include +#include +#include + +#include "compiler.h" + +/* Use low 6 bits to encode test type */ +#define TTYPE_MASK 0x3f +#define TPASS 0 /* Test passed flag */ +#define TFAIL 1 /* Test failed flag */ +#define TBROK 2 /* Test broken flag */ +#define TWARN 4 /* Test warning flag */ +#define TRETR 8 /* Test retire flag */ +#define TINFO 16 /* Test information flag */ +#define TCONF 32 /* Test not appropriate for configuration flag */ +#define TTYPE_RESULT(ttype) ((ttype) & TTYPE_MASK) + +#define TERRNO 0x100 /* Append errno information to output */ +#define TTERRNO 0x200 /* Append TEST_ERRNO information to output */ +#define TRERRNO 0x300 /* Capture errno information from TEST_RETURN to + output; useful for pthread-like APIs :). */ + +/* + * To determine if you are on a Umk or Unicos system, + * use sysconf(_SC_CRAY_SYSTEM). But since _SC_CRAY_SYSTEM + * is not defined until 90, it will be define here if not already + * defined. + * if (sysconf(_SC_CRAY_SYSTEM) == 1) + * on UMK + * else # returned 0 or -1 + * on Unicos + * This is only being done on CRAY systems. + */ +#ifdef CRAY +#ifndef _SC_CRAY_SYSTEM +#define _SC_CRAY_SYSTEM 140 +#endif /* ! _SC_CRAY_SYSTEM */ +#endif /* CRAY */ + +/* + * Ensure that NUMSIGS is defined. + * It should be defined in signal.h or sys/signal.h on + * UNICOS/mk and IRIX systems. On UNICOS systems, + * it is not defined, thus it is being set to UNICOS's NSIG. + * Note: IRIX's NSIG (signals are 1-(NSIG-1)) + * is not same meaning as UNICOS/UMK's NSIG (signals 1-NSIG) + */ +#ifndef NUMSIGS +#define NUMSIGS NSIG +#endif + + +/* defines for unexpected signal setup routine (set_usig.c) */ +#define FORK 1 /* SIGCLD is to be ignored */ +#define NOFORK 0 /* SIGCLD is to be caught */ +#define DEF_HANDLER SIG_ERR /* tells set_usig() to use default signal handler */ + +/* + * The following defines are used to control tst_res and t_result reporting. + */ + +#define TOUTPUT "TOUTPUT" /* The name of the environment variable */ + /* that can be set to one of the following */ + /* strings to control tst_res output */ + /* If not set, TOUT_VERBOSE_S is assumed */ + +#define TOUT_VERBOSE_S "VERBOSE" /* All test cases reported */ +#define TOUT_NOPASS_S "NOPASS" /* No pass test cases are reported */ +#define TOUT_DISCARD_S "DISCARD" /* No output is reported */ + +/* + * The following defines are used to control tst_tmpdir, tst_wildcard and t_mkchdir + */ + +#define TDIRECTORY "TDIRECTORY" /* The name of the environment variable */ + /* that if is set, the value (directory) */ + /* is used by all tests as their working */ + /* directory. tst_rmdir and t_rmdir will */ + /* not attempt to clean up. */ + /* This environment variable should only */ + /* be set when doing system testing since */ + /* tests will collide and break and fail */ + /* because of setting it. */ + +#define TEMPDIR "/tmp" /* This is the default temporary directory. */ + /* The environment variable TMPDIR is */ + /* used prior to this valid by tempnam(3). */ + /* To control the base location of the */ + /* temporary directory, set the TMPDIR */ + /* environment variable to desired path */ + +/* + * The following define contains the name of an environmental variable + * that can be used to specify the number of iterations. + * It is supported in parse_opts.c and USC_setup.c. + */ +#define USC_ITERATION_ENV "USC_ITERATIONS" + +/* + * The following define contains the name of an environmental variable + * that can be used to specify to iteration until desired time + * in floating point seconds has gone by. + * Supported in USC_setup.c. + */ +#define USC_LOOP_WALLTIME "USC_LOOP_WALLTIME" + +/* + * The following define contains the name of an environmental variable + * that can be used to specify that no functional checks are wanted. + * It is supported in parse_opts.c and USC_setup.c. + */ +#define USC_NO_FUNC_CHECK "USC_NO_FUNC_CHECK" + +/* + * The following define contains the name of an environmental variable + * that can be used to specify the delay between each loop iteration. + * The value is in seconds (fractional numbers are allowed). + * It is supported in parse_opts.c. + */ +#define USC_LOOP_DELAY "USC_LOOP_DELAY" + +/* + * fork() can't be used on uClinux systems, so use FORK_OR_VFORK instead, + * which will run vfork() on uClinux. + * mmap() doesn't support MAP_PRIVATE on uClinux systems, so use + * MAP_PRIVATE_EXCEPT_UCLINUX instead, which will skip the option on uClinux. + * If MAP_PRIVATE really is required, the test can not be run on uClinux. + */ +#ifdef UCLINUX +#define FORK_OR_VFORK vfork +#define MAP_PRIVATE_EXCEPT_UCLINUX 0 +#else +#define FORK_OR_VFORK fork +#define MAP_PRIVATE_EXCEPT_UCLINUX MAP_PRIVATE +#endif + +/* + * lib/forker.c + */ +extern int Forker_pids[]; +extern int Forker_npids; + +/* lib/tst_res.c */ +const char *strttype(int ttype); +void tst_res(int ttype, char *fname, char *arg_fmt, ...) + __attribute__ ((format (printf, 3, 4))); +void tst_resm(int ttype, char *arg_fmt, ...) + __attribute__ ((format (printf, 2, 3))); +void tst_brk(int ttype, char *fname, void (*func)(void), char *arg_fmt, ...) + __attribute__ ((format (printf, 4, 5))); +void tst_brkm(int ttype, void (*func)(void), char *arg_fmt, ...) + __attribute__ ((format (printf, 3, 4))) LTP_ATTRIBUTE_NORETURN; +void tst_require_root(void (*func)(void)); +int tst_environ(void); +void tst_exit(void) LTP_ATTRIBUTE_NORETURN; +void tst_flush(void); + +extern int Tst_count; + +/* lib/tst_sig.c */ +void tst_sig(int fork_flag, void (*handler)(), void (*cleanup)()); + +/* lib/tst_tmpdir.c */ +void tst_tmpdir(void); +void tst_rmdir(void); +char *get_tst_tmpdir(void); + +/* lib/get_high_address.c */ +char *get_high_address(void); + +/* lib/tst_kvercmp.c */ +void tst_getkver(int *k1, int *k2, int *k3); +int tst_kvercmp(int r1, int r2, int r3); + +/* lib/tst_is_cwd.c */ +int tst_is_cwd_nfs(void); +int tst_is_cwd_v9fs(void); +int tst_is_cwd_tmpfs(void); +int tst_is_cwd_ramfs(void); + +/* lib/tst_cwd_has_free.c */ +int tst_cwd_has_free(int required_kib); + +/* lib/self_exec.c */ +void maybe_run_child(void (*child)(), char *fmt, ...); +int self_exec(char *argv0, char *fmt, ...); + +/* Functions from lib/cloner.c */ +int ltp_clone(unsigned long clone_flags, int (*fn)(void *arg), void *arg, + size_t stack_size, void *stack); +int ltp_clone_malloc(unsigned long clone_flags, int (*fn)(void *arg), + void *arg, size_t stacksize); +int ltp_clone_quick(unsigned long clone_flags, int (*fn)(void *arg), + void *arg); +#define clone(...) use_the_ltp_clone_functions,do_not_use_clone + +/* Functions from lib/mount_utils.c */ +char *get_block_device(const char *path); +char *get_mountpoint(const char *path); + +/* Function from lib/get_path.c */ +int tst_get_path(const char *prog_name, char *buf, size_t buf_len); + +#ifdef TST_USE_COMPAT16_SYSCALL +#define TCID_BIT_SUFFIX "_16" +#elif TST_USE_NEWER64_SYSCALL +#define TCID_BIT_SUFFIX "_64" +#else +#define TCID_BIT_SUFFIX "" +#endif +#define TCID_DEFINE(ID) char *TCID = (#ID TCID_BIT_SUFFIX) + +#endif /* __TEST_H__ */ diff --git a/ltp_framework/include/tlibio.h b/ltp_framework/include/tlibio.h new file mode 100644 index 0000000..0ac52e4 --- /dev/null +++ b/ltp_framework/include/tlibio.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ + +#define LIO_IO_SYNC 00001 /* read/write */ +#define LIO_IO_ASYNC 00002 /* reada/writea/aio_write/aio_read */ +#define LIO_IO_SLISTIO 00004 /* single stride sync listio */ +#define LIO_IO_ALISTIO 00010 /* single stride async listio */ +#define LIO_IO_SYNCV 00020 /* single-buffer readv/writev */ +#define LIO_IO_SYNCP 00040 /* pread/pwrite */ + +#ifdef sgi +#define LIO_IO_ATYPES 00077 /* all io types */ +#define LIO_IO_TYPES 00061 /* all io types, non-async */ +#endif /* sgi */ +#if defined(__linux__) && !defined(__UCLIBC__) +#define LIO_IO_TYPES 00061 /* all io types */ +#define LIO_IO_ATYPES 00077 /* all io types */ +#endif +#if defined(__sun) || defined(__hpux) || defined(_AIX) || defined(__UCLIBC__) +#define LIO_IO_TYPES 00021 /* all io types except pread/pwrite */ +#endif /* linux */ +#ifdef CRAY +#define LIO_IO_TYPES 00017 /* all io types */ +#endif /* CRAY */ + +#ifndef LIO_IO_ATYPES +#define LIO_IO_ATYPES LIO_IO_TYPES +#endif + +#define LIO_WAIT_NONE 00010000 /* return asap -- use with care */ +#define LIO_WAIT_ACTIVE 00020000 /* spin looking at iosw fields, or EINPROGRESS */ +#define LIO_WAIT_RECALL 00040000 /* call recall(2)/aio_suspend(3) */ +#define LIO_WAIT_SIGPAUSE 00100000 /* call pause */ +#define LIO_WAIT_SIGACTIVE 00200000 /* spin waiting for signal */ +#if defined(sgi) || defined(__linux__) +#define LIO_WAIT_CBSUSPEND 00400000 /* aio_suspend waiting for callback */ +#define LIO_WAIT_SIGSUSPEND 01000000 /* aio_suspend waiting for signal */ +#define LIO_WAIT_ATYPES 01760000 /* all async wait types, except nowait */ +#define LIO_WAIT_TYPES 00020000 /* all sync wait types (sorta) */ +#endif /* sgi */ +#if defined(__sun) || defined(__hpux) || defined(_AIX) +#define LIO_WAIT_TYPES 00300000 /* all wait types, except nowait */ +#endif /* linux */ +#ifdef CRAY +#define LIO_WAIT_TYPES 00360000 /* all wait types, except nowait */ +#endif /* CRAY */ + +/* meta wait io */ +/* 00 000 0000 */ + +#if defined(sgi) || defined(__linux__) +/* all callback wait types */ +#define LIO_WAIT_CBTYPES (LIO_WAIT_CBSUSPEND) +/* all signal wait types */ +#define LIO_WAIT_SIGTYPES (LIO_WAIT_SIGPAUSE|LIO_WAIT_SIGACTIVE|LIO_WAIT_SIGSUSPEND) +/* all aio_{read,write} or lio_listio */ +#define LIO_IO_ASYNC_TYPES (LIO_IO_ASYNC|LIO_IO_SLISTIO|LIO_IO_ALISTIO) +#endif /* sgi */ +#if defined(__sun) || defined(__hpux) || defined(_AIX) +/* all signal wait types */ +#define LIO_WAIT_SIGTYPES (LIO_WAIT_SIGPAUSE) +#endif /* linux */ +#ifdef CRAY +/* all signal wait types */ +#define LIO_WAIT_SIGTYPES (LIO_WAIT_SIGPAUSE|LIO_WAIT_SIGACTIVE) +#endif /* CRAY */ + +/* + * This bit provides a way to randomly pick an io type and wait method. + * lio_read_buffer() and lio_write_buffer() functions will call + * lio_random_methods() with the given method. + */ +#define LIO_RANDOM 010000000 + +/* + * This bit provides a way for the programmer to use async i/o with + * signals and to use their own signal handler. By default, + * the signal will only be given to the system call if the wait + * method is LIO_WAIT_SIGPAUSE or LIO_WAIT_SIGACTIVE. + * Whenever these wait methods are used, libio signal handler + * will be used. + */ +#define LIO_USE_SIGNAL 020000000 + +/* + * prototypes/structures for functions in the libio.c module. See comments + * in that module, or man page entries for information on the individual + * functions. + */ + +int stride_bounds(int offset, int stride, int nstrides, + int bytes_per_stride, int *min_byte, int *max_byte); + +int lio_set_debug(int level); +int lio_parse_io_arg1(char *string); +void lio_help1(char *prefex); +int lio_parse_io_arg2(char *string, char **badtoken); +void lio_help2(char *prefex); +int lio_write_buffer(int fd, int method, char *buffer, int size, + int sig, char **errmsg, long wrd); + +int lio_read_buffer(int fd, int method, char *buffer, int size, + int sig, char **errmsg, long wrd); +int lio_random_methods(long mask); + +#if CRAY +#include +int lio_wait4asyncio(int method, int fd, struct iosw **statptr); +int lio_check_asyncio(char *io_type, int size, struct iosw *status); +#endif /* CRAY */ +#if defined (sgi) +#include +int lio_wait4asyncio(int method, int fd, aiocb_t *aiocbp); +int lio_check_asyncio(char *io_type, int size, aiocb_t *aiocbp, int method); +#endif /* sgi */ +#if defined(__linux__) && !defined(__UCLIBC__) +#include +int lio_wait4asyncio(int method, int fd, struct aiocb *aiocbp); +int lio_check_asyncio(char *io_type, int size, struct aiocb *aiocbp, int method); +#endif + +/* + * Define the structure that contains the infomation that is used + * by the parsing and help functions. + */ +struct lio_info_type { + char *token; + int bits; + char *desc; +}; + + diff --git a/ltp_framework/include/usctest.h b/ltp_framework/include/usctest.h new file mode 100644 index 0000000..04f0e9c --- /dev/null +++ b/ltp_framework/include/usctest.h @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ + +/* $Id: usctest.h,v 1.14 2009/08/28 10:03:01 vapier Exp $ */ + +/********************************************************** + * + * IRIX/Linux Feature Test and Evaluation - Silicon Graphics, Inc. + * + * FUNCTION NAME : usctest.h + * + * FUNCTION TITLE : System Call Test Macros + * + * SYNOPSIS: + * See DESCRIPTION below. + * + * AUTHOR : William Roske + * + * INITIAL RELEASE : UNICOS 7.0 + * + * DESCRIPTION + * TEST(SCALL) - calls a system call + * TEST_VOID(SCALL) - same as TEST() but for syscalls with no return value. + * TEST_CLEANUP - print the log of errno return counts if STD_ERRNO_LOG + * is set. + * TEST_PAUSEF(HAND) - Pause for SIGUSR1 if the pause flag is set. + * Use "hand" as the interrupt handling function + * TEST_PAUSE - Pause for SIGUSR1 if the pause flag is set. + * Use internal function to do nothing on signal and go on. + * TEST_LOOPING(COUNTER) - Conditional to check if test should + * loop. Evaluates to TRUE (1) or FALSE (0). + * TEST_ERROR_LOG(eno) - log that this errno was received, + * if STD_ERRNO_LOG is set. + * TEST_EXP_ENOS(array) - set the bits in TEST_VALID_ENO array at + * positions specified in integer "array" + * + * RETURN VALUE + * TEST(SCALL) - Global Variables set: + * long TEST_RETURN=return code from SCALL + * int TEST_ERRNO=value of errno at return from SCALL + * TEST_VOID(SCALL) - Global Variables set: + * int TEST_ERRNO=value of errno at return from SCALL + * TEST_CLEANUP - None. + * TEST_PAUSEF(HAND) - None. + * TEST_PAUSE - None. + * TEST_LOOPING(COUNTER) - True if COUNTER < STD_LOOP_COUNT or + * STD_INFINITE is set. + * TEST_ERROR_LOG(eno) - None + * TEST_EXP_ENOS(array) - None + * + * KNOWN BUGS + * If you use the TEST_PAUSE or TEST_LOOPING macros, you must + * link in parse_opts.o, which contains the code for those functions. + * + *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ + +#ifndef __USCTEST_H__ +#define __USCTEST_H__ 1 + +#ifndef _SC_CLK_TCK +#include +#endif + +#include + +/* + * Ensure that PATH_MAX is defined + */ +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif + +#ifndef CRAY +#ifndef BSIZE +#define BSIZE BBSIZE +#endif +#endif + +/*********************************************************************** + * Define option_t structure type. + * Entries in this struct are used by the parse_opts routine + * to indicate valid options and return option arguments + ***********************************************************************/ +typedef struct { + char *option; /* Valid option string (one option only) like "a:" */ + int *flag; /* pointer to location to set true if option given */ + char **arg; /* pointer to location to place argument, if needed */ +} option_t; + +/*********************************************************************** + * The following globals are defined in parse_opts.c but must be + * externed here because they are used in the macros defined below. + ***********************************************************************/ +extern int STD_FUNCTIONAL_TEST, /* turned off by -f to not do functional test */ + STD_TIMING_ON, /* turned on by -t to print timing stats */ + STD_PAUSE, /* turned on by -p to pause before loop */ + STD_INFINITE, /* turned on by -i0 to loop forever */ + STD_LOOP_COUNT, /* changed by -in to set loop count to n */ + STD_ERRNO_LOG, /* turned on by -e to log errnos returned */ + STD_ERRNO_LIST[], /* counts of errnos returned. indexed by errno */ + STD_COPIES, + STD_argind; + +extern float STD_LOOP_DURATION, /* wall clock time to iterate */ + STD_LOOP_DELAY; /* delay time after each iteration */ + +#define USC_MAX_ERRNO 2000 + +/********************************************************************** + * Prototype for parse_opts routine + **********************************************************************/ +extern char *parse_opts(int ac, char **av, const option_t *user_optarr, void (*uhf)()); + + +/* + * define a structure + */ +struct usc_errno_t { + int flag; +}; + +/*********************************************************************** + **** + **** + **** + **********************************************************************/ +#ifdef _USC_LIB_ + +extern long TEST_RETURN; +extern int TEST_ERRNO; +extern struct usc_errno_t TEST_VALID_ENO[USC_MAX_ERRNO]; + +#else +/*********************************************************************** + * Global array of bit masks to indicate errnos that are expected. + * Bits set by TEST_EXP_ENOS() macro and used by TEST_CLEANUP() macro. + ***********************************************************************/ +struct usc_errno_t TEST_VALID_ENO[USC_MAX_ERRNO]; + +/*********************************************************************** + * Globals for returning the return code and errno from the system call + * test macros. + ***********************************************************************/ +long TEST_RETURN; +int TEST_ERRNO; + +#endif /* _USC_LIB_ */ + +/*********************************************************************** + * structure for timing accumulator and counters + ***********************************************************************/ +struct tblock { + long tb_max; + long tb_min; + long tb_total; + long tb_count; +}; + +/*********************************************************************** + * The following globals are externed here so that they are accessable + * in the macros that follow. + ***********************************************************************/ +extern struct tblock tblock; +extern void STD_go(); +extern int (*_TMP_FUNC)(void); +extern void STD_opts_help(); + + +/*********************************************************************** + * TEST: calls a system call + * + * parameters: + * SCALL = system call and parameters to execute + * + ***********************************************************************/ +#define TEST(SCALL) \ + do { \ + errno = 0; \ + TEST_RETURN = SCALL; \ + TEST_ERRNO = errno; \ + } while (0) + +/*********************************************************************** + * TEST_VOID: calls a system call + * + * parameters: + * SCALL = system call and parameters to execute + * + * Note: This is IDENTICAL to the TEST() macro except that it is intended + * for use with syscalls returning no values (void syscall()). The + * Typecasting nothing (void) into an unsigned integer causes compilation + * errors. + * + ***********************************************************************/ +#define TEST_VOID(SCALL) do { errno = 0; SCALL; TEST_ERRNO = errno; } while (0) + +/*********************************************************************** + * TEST_CLEANUP: print system call timing stats and errno log entries + * to stdout if STD_TIMING_ON and STD_ERRNO_LOG are set, respectively. + * Do NOT print ANY information if no system calls logged. + * + * parameters: + * none + * + ***********************************************************************/ +#define TEST_CLEANUP \ +do { \ + int i; \ + if (!STD_ERRNO_LOG) \ + break; \ + for (i = 0; i < USC_MAX_ERRNO; ++i) { \ + if (!STD_ERRNO_LIST[i]) \ + continue; \ + tst_resm(TINFO, "ERRNO %d:\tReceived %d Times%s", \ + i, STD_ERRNO_LIST[i], \ + TEST_VALID_ENO[i].flag ? "" : " ** UNEXPECTED **"); \ + } \ +} while (0) + +/*********************************************************************** + * TEST_PAUSEF: Pause for SIGUSR1 if the pause flag is set. + * Set the user specified function as the interrupt + * handler instead of "STD_go" + * + * parameters: + * none + * + ***********************************************************************/ +#define TEST_PAUSEF(HANDLER) \ +do { \ + if (STD_PAUSE) { \ + _TMP_FUNC = (int (*)())signal(SIGUSR1, HANDLER); \ + pause(); \ + signal(SIGUSR1, (void (*)())_TMP_FUNC); \ + } \ +} while (0) + +/*********************************************************************** + * TEST_PAUSE: Pause for SIGUSR1 if the pause flag is set. + * Just continue when signal comes in. + * + * parameters: + * none + * + ***********************************************************************/ +#define TEST_PAUSE usc_global_setup_hook(); +int usc_global_setup_hook(); + +/*********************************************************************** + * TEST_LOOPING now call the usc_test_looping function. + * The function will return 1 if the test should continue + * iterating. + * + ***********************************************************************/ +#define TEST_LOOPING usc_test_looping +int usc_test_looping(int counter); + +/*********************************************************************** + * TEST_ERROR_LOG(eno): log this errno if STD_ERRNO_LOG flag set + * + * parameters: + * int eno: the errno location in STD_ERRNO_LIST to log. + * + ***********************************************************************/ +#define TEST_ERROR_LOG(eno) \ +do { \ + int _eno = (eno); \ + if ((STD_ERRNO_LOG) && (_eno < USC_MAX_ERRNO)) \ + STD_ERRNO_LIST[_eno]++; \ +} while (0) + +/*********************************************************************** + * TEST_EXP_ENOS(array): set the bits associated with the nput errnos + * in the TEST_VALID_ENO array. + * + * parameters: + * int array[]: a zero terminated array of errnos expected. + * + ***********************************************************************/ +#define TEST_EXP_ENOS(array) \ +do { \ + int i = 0; \ + while (array[i] != 0) { \ + if (array[i] < USC_MAX_ERRNO) \ + TEST_VALID_ENO[array[i]].flag = 1; \ + ++i; \ + } \ +} while (0) + +#endif /* end of __USCTEST_H__ */ diff --git a/ltp_framework/include/write_log.h b/ltp_framework/include/write_log.h new file mode 100644 index 0000000..84d6313 --- /dev/null +++ b/ltp_framework/include/write_log.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +#ifndef _WRITE_LOG_H_ +#define _WRITE_LOG_H_ + +/* + * Constants defining the max size of various wlog_rec fields. ANY SIZE + * CHANGES HERE MUST BE REFLECTED IN THE WLOG_REC_DISK STRUCTURE DEFINED + * BELOW. + */ + +#define WLOG_MAX_PATH 128 +#define WLOG_MAX_PATTERN 64 +#define WLOG_MAX_HOST 8 +#define WLOG_REC_MAX_SIZE (sizeof(struct wlog_rec)+WLOG_MAX_PATH+WLOG_MAX_PATTERN+WLOG_MAX_HOST+2) + +/* + * User view of a write log record. Note that this is not necessiliary + * how the data is formatted on disk (signifigant compression occurrs), so + * don't expect to od the write log file and see things formatted this way. + */ + +struct wlog_rec { + int w_pid; /* pid doing the write */ + int w_offset; /* file offset */ + int w_nbytes; /* # bytes written */ + int w_oflags; /* low-order open() flags */ + int w_done; /* 1 if io confirmed done */ + int w_async; /* 1 if async write (writea) */ + + char w_host[WLOG_MAX_HOST+1]; /* host doing write - */ + /* null terminated */ + int w_hostlen; /* host name length */ + char w_path[WLOG_MAX_PATH+1]; /* file written to - */ + /* null terminated */ + int w_pathlen; /* file name length */ + char w_pattern[WLOG_MAX_PATTERN+1]; /* pattern written - */ + /* null terminated */ + int w_patternlen; /* pattern length */ +}; + +#ifndef uint +#define uint unsigned int +#endif + +/* + * On-disk structure of a wlog_rec. Actually, the record consists of + * 3 parts: [wlog_rec_disk structure][variable length data][length] + * where length is a 2 byte field containing the total record length + * (including the 2 bytes). It is used for scanning the logfile in reverse + * order. + * + * The variable length data includes the path, host, and pattern (in that + * order). The lengths of these pieces of data are held in the + * wlog_rec_disk structure. Thus, the actual on-disk record looks like + * this (top is lower byte offset): + * + * struct wlog_rec_disk + * path (w_pathlen bytes - not null terminated) + * host (w_hostlen bytes - not null terminated) + * pattern (w_patternlen bytes - not null terminated) + * 2-byte record length + * + * Another way of looking at it is: + * + * --> + * --> + * + * The maximum length of this record is defined by the WLOG_REC_MAX_SIZE + * record. Note that the 2-byte record length forces this to be + * <= 64k bytes. + * + * Note that there is lots of bit-masking done here. The w_pathlen, + * w_hostlen, and w_patternlen fields MUST have enough bits to hold + * WLOG_MAX_PATH, WLOG_MAX_HOST, and WLOG_MAX_PATTERN bytes respectivly. + */ + +struct wlog_rec_disk { +#ifdef CRAY + uint w_offset : 44; /* file offset */ + uint w_extra0 : 20; /* EXTRA BITS IN WORD 0 */ +#else + /* NB: sgi is pissy about fields > 32 bit, even cc -mips3 */ + uint w_offset : 32; /* file offset */ + uint w_extra0 : 32; /* EXTRA BITS IN WORD 0 */ +#endif + + uint w_nbytes : 32; /* # bytes written */ + uint w_oflags : 32; /* low-order open() flags */ + + uint w_pid : 17; /* pid doing the write */ + uint w_pathlen : 7; /* length of file path */ + uint w_patternlen: 6; /* length of pattern */ + uint w_hostlen : 4; /* length of host */ + uint w_done : 1; /* 1 if io confirmed done */ + uint w_async : 1; /* 1 if async write (writea) */ + uint w_extra2 : 28; /* EXTRA BITS IN WORD 2 */ +}; + +/* + * write log file datatype. wlog_open() initializes this structure + * which is then passed around to the various wlog_xxx routines. + */ + +struct wlog_file { + int w_afd; /* append fd */ + int w_rfd; /* random-access fd */ + char w_file[1024]; /* name of the write_log */ +}; + +/* + * return value defines for the user-supplied function to + * wlog_scan_backward(). + */ + +#define WLOG_STOP_SCAN 0 +#define WLOG_CONTINUE_SCAN 1 + +/* + * wlog prototypes + */ + +#if __STDC__ +extern int wlog_open(struct wlog_file *wfile, int trunc, int mode); +extern int wlog_close(struct wlog_file *wfile); +extern int wlog_record_write(struct wlog_file *wfile, + struct wlog_rec *wrec, long offset); +extern int wlog_scan_backward(struct wlog_file *wfile, int nrecs, + int (*func)(struct wlog_rec *rec), + long data); +#else +int wlog_open(); +int wlog_close(); +int wlog_record_write(); +int wlog_scan_backward(); +#endif + +extern char Wlog_Error_String[]; + +#endif /* _WRITE_LOG_H_ */ + diff --git a/ltp_framework/lib/Makefile b/ltp_framework/lib/Makefile new file mode 100644 index 0000000..661c0a1 --- /dev/null +++ b/ltp_framework/lib/Makefile @@ -0,0 +1,45 @@ +# +# lib Makefile. +# +# Copyright (C) 2009, Cisco Systems 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Garrett Cooper, July 2009 +# + +top_srcdir ?= .. + +include $(top_srcdir)/include/mk/env_pre.mk + +ifeq ($(UCLINUX),1) +CFLAGS += -D_USC_LIB_ +endif + +#CPPFLAGS += -DGARRETT_IS_A_PEDANTIC_BASTARD + +FILTER_OUT_LIBSRCS := mount_utils.c + +LIB := libltp.a + +pc_file := $(DESTDIR)/$(datarootdir)/pkgconfig/ltp.pc + +INSTALL_TARGETS := $(pc_file) + +$(pc_file): + test -d "$(@D)" || mkdir -p "$(@D)" + install -m $(INSTALL_MODE) "$(builddir)/$(@F)" "$@" + +include $(top_srcdir)/include/mk/lib.mk diff --git a/ltp_framework/lib/cloner.c b/ltp_framework/lib/cloner.c new file mode 100644 index 0000000..bf9eed1 --- /dev/null +++ b/ltp_framework/lib/cloner.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) International Business Machines Corp., 2009 + * Some wrappers for clone functionality. Thrown together by Serge Hallyn + * based on existing clone usage in ltp. + * + * 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 + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include /* fork, getpid, sleep */ +#include +#include /* exit */ +#include /* clone */ +#include "test.h" + +#undef clone /* we want to use clone() */ + +/* copied from several other files under ltp */ +#if defined (__s390__) || (__s390x__) +#define clone __clone +extern int __clone(int(void*),void*,int,void*); +#elif defined(__ia64__) +#define clone2 __clone2 +/* Prototype provided by David Mosberger */ +extern int __clone2(int (*fn) (void *arg), void *child_stack_base, + size_t child_stack_size, int flags, void *arg, + pid_t *parent_tid, void *tls, pid_t *child_tid); +#endif + +/*********************************************************************** + * ltp_clone: wrapper for clone to hide the architecture dependencies. + * 1. hppa takes bottom of stack and no stacksize (stack grows up) + * 2. __ia64__ takes bottom of stack and uses clone2 + * 3. all others take top of stack (stack grows down) + ***********************************************************************/ +int +ltp_clone(unsigned long clone_flags, int (*fn)(void *arg), void *arg, + size_t stack_size, void *stack) +{ + int ret; + +#if defined(__hppa__) + ret = clone(fn, stack, clone_flags, arg); +#elif defined(__ia64__) + ret = clone2(fn, stack, stack_size, clone_flags, arg, NULL, NULL, NULL); +#else + /* + * For archs where stack grows downwards, stack points to the topmost + * address of the memory space set up for the child stack. + */ + ret = clone(fn, (stack ? stack + stack_size : NULL), + clone_flags, arg); +#endif + + return ret; +} + +/*********************************************************************** + * ltp_clone_malloc: also does the memory allocation for clone with a + * caller-specified size. + ***********************************************************************/ +int +ltp_clone_malloc(unsigned long clone_flags, int (*fn)(void *arg), void *arg, + size_t stack_size) +{ + void *stack; + int ret; + int saved_errno; + + if ((stack = malloc(stack_size)) == NULL) + return -1; + + ret = ltp_clone(clone_flags, fn, arg, stack_size, stack); + + if (ret == -1) { + saved_errno = errno; + free(stack); + errno = saved_errno; + } + + return ret; +} + +/*********************************************************************** + * ltp_clone_quick: calls ltp_clone_malloc with predetermined stack size. + * Experience thus far suggests that one page is often insufficient, + * while 4*getpagesize() seems adequate. + ***********************************************************************/ +int +ltp_clone_quick(unsigned long clone_flags, int (*fn)(void *arg), void *arg) +{ + size_t stack_size = getpagesize() * 4; + + return ltp_clone_malloc(clone_flags, fn, arg, stack_size); +} \ No newline at end of file diff --git a/ltp_framework/lib/dataascii.c b/ltp_framework/lib/dataascii.c new file mode 100644 index 0000000..0188eca --- /dev/null +++ b/ltp_framework/lib/dataascii.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +#include +#include +#include "dataascii.h" + +#define CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghjiklmnopqrstuvwxyz\n" +#define CHARS_SIZE sizeof(CHARS) + +#ifdef UNIT_TEST +#include /* malloc */ +#endif + +static char Errmsg[80]; + +int +dataasciigen(listofchars, buffer, bsize, offset) +char *listofchars; /* a null terminated list of characters */ +char *buffer; +int bsize; +int offset; +{ + int cnt; + int total; + int ind; /* index into CHARS array */ + char *chr; + int chars_size; + char *charlist; + + chr=buffer; + total=offset+bsize; + + if (listofchars == NULL) { + charlist=CHARS; + chars_size=CHARS_SIZE; + } + else { + charlist=listofchars; + chars_size=strlen(listofchars); + } + + for (cnt=offset; cnt +#include +#include /* memset */ +#include /* rand */ +#include "databin.h" + +#if UNIT_TEST +#include +#endif + +static char Errmsg[80]; + +void +databingen (mode, buffer, bsize, offset) +int mode; /* either a, c, r, o, z or C */ +char *buffer; /* buffer pointer */ +int bsize; /* size of buffer */ +int offset; /* offset into the file where buffer starts */ +{ +int ind; + + switch (mode) + { + default: + case 'a': /* alternating bit pattern */ + memset(buffer,0x55,bsize); + break; + + case 'c': /* checkerboard pattern */ + memset(buffer,0xf0,bsize); + break; + + case 'C': /* */ + for (ind=0;ind< bsize;ind++) { + buffer[ind] = ((offset+ind)%8 & 0177); + } + break; + + case 'o': + memset(buffer,0xff,bsize); + break; + + case 'z': + memset(buffer,0x0,bsize); + break; + + case 'r': /* random */ + for (ind=0;ind< bsize;ind++) { + buffer[ind] = (rand () & 0177) | 0100; + } + } +} + +/*********************************************************************** + * + * return values: + * >= 0 : error at byte offset into the file, offset+buffer[0-(bsize-1)] + * < 0 : no error + ***********************************************************************/ +int +databinchk(mode, buffer, bsize, offset, errmsg) +int mode; /* either a, c, r, z, o, or C */ +char *buffer; /* buffer pointer */ +int bsize; /* size of buffer */ +int offset; /* offset into the file where buffer starts */ +char **errmsg; +{ + int cnt; + unsigned char *chr; + int total; + long expbits; + long actbits; + + chr = (unsigned char *) buffer; + total=bsize; + + if (errmsg != NULL) { + *errmsg = Errmsg; + } + + switch (mode) + { + default: + case 'a': /* alternating bit pattern */ + expbits=0x55; + break; + + case 'c': /* checkerboard pattern */ + expbits=0xf0; + break; + + case 'C': /* counting pattern */ + for (cnt=0;cnt< bsize;cnt++) { + expbits = ((offset+cnt)%8 & 0177); + + if (buffer[cnt] != expbits) { + sprintf(Errmsg, + "data mismatch at offset %d, exp:%#lo, act:%#o", + offset+cnt, expbits, buffer[cnt]); + return offset+cnt; + } + } + sprintf(Errmsg, "all %d bytes match desired pattern", bsize); + return -1; + + case 'o': + expbits=0xff; + break; + + case 'z': + expbits=0; + break; + + case 'r': + return -1; /* no check can be done for random */ + } + + for (cnt=0; cnt< word-offset in file (same #) >< pid > + +1234567890123456789012345678901234567890123456789012345678901234 +________________________________________________________________ +< pid >< offset in file of this word >< pid > + + +8 bits to a bytes == character + NBPW 8 +************/ + +#include +#include +#ifdef UNIT_TEST +#include +#include +#endif + +static char Errmsg[80]; + +#define LOWER16BITS(X) (X & 0177777) +#define LOWER32BITS(X) (X & 0xffffffff) + +/*** +#define HIGHBITS(WRD, bits) ( (-1 << (64-bits)) & WRD) +#define LOWBITS(WRD, bits) ( (-1 >> (64-bits)) & WRD) +****/ + +#define NBPBYTE 8 /* number bits per byte */ + +#ifndef DEBUG +#define DEBUG 0 +#endif + +/*********************************************************************** + * + * + * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 14 15 bytes + * 1234567890123456789012345678901234567890123456789012345678901234 bits + * ________________________________________________________________ 1 word + * < pid >< offset in file of this word >< pid > + * + * the words are put together where offset zero is the start. + * thus, offset 16 is the start of the second full word + * Thus, offset 8 is in middle of word 1 + ***********************************************************************/ +int +datapidgen(pid, buffer, bsize, offset) +int pid; +char *buffer; +int bsize; +int offset; +{ +#if CRAY + + int cnt; + int tmp; + char *chr; + long *wptr; + long word; + int woff; /* file offset for the word */ + int boff; /* buffer offset or index */ + int num_full_words; + + num_full_words = bsize/NBPW; + boff = 0; + + if (cnt=(offset % NBPW)) { /* partial word */ + + woff = offset - cnt; +#if DEBUG +printf("partial at beginning, cnt = %d, woff = %d\n", cnt, woff); +#endif + + word = ((LOWER16BITS(pid) << 48) | (LOWER32BITS(woff) << 16) | LOWER16BITS(pid)); + + chr = (char *)&word; + + for (tmp=0; tmp +#include +#include +#include +#include +#include +#include +#include +#include +#include /* memset, strerror */ +#include "file_lock.h" + + +#ifndef EFSEXCLWR +#define EFSEXCLWR 503 +#endif + +/* + * String containing the last system call. + * + */ +char Fl_syscall_str[128]; + +static char errmsg[256]; + +/*********************************************************************** + * + * Test interface to the fcntl system call. + * It will loop if the LOCK_NB flags is NOT set. + ***********************************************************************/ +int +file_lock(fd, flags, errormsg) +int fd; +int flags; +char **errormsg; +{ + register int cmd, ret; + struct flock flocks; + + memset(&flocks, 0, sizeof(struct flock)); + + if (flags&LOCK_NB) + cmd = F_SETLK; + else + cmd = F_SETLKW; + + flocks.l_whence = 0; + flocks.l_start = 0; + flocks.l_len = 0; + + if (flags&LOCK_UN) + flocks.l_type = F_UNLCK; + else if (flags&LOCK_EX) + flocks.l_type = F_WRLCK; + else if (flags&LOCK_SH) + flocks.l_type = F_RDLCK; + else { + errno = EINVAL; + if (errormsg != NULL) { + sprintf(errmsg, + "Programmer error, called file_lock with in valid flags\n"); + *errormsg = errmsg; + } + return -1; + } + + sprintf(Fl_syscall_str, + "fcntl(%d, %d, &flocks): type:%d whence:%d, start:%lld len:%lld\n", + fd, cmd, flocks.l_type, flocks.l_whence, + (long long)flocks.l_start, (long long)flocks.l_len); + + while (1) { + ret = fcntl(fd, cmd, &flocks); + + if (ret < 0) { + if (cmd == F_SETLK) + switch (errno) { + /* these errors are okay */ + case EACCES: /* Permission denied */ + case EINTR: /* interrupted system call */ +#ifdef EFILESH + case EFILESH: /* file shared */ +#endif + case EFSEXCLWR: /* File is write protected */ + continue; /* retry getting lock */ + } + if (errormsg != NULL) { + sprintf(errmsg, "fcntl(%d, %d, &flocks): errno:%d %s\n", + fd, cmd, errno, strerror(errno)); + *errormsg = errmsg; + } + return -1; + } + break; + } + + return ret; + +} /* end of file_lock */ + +/*********************************************************************** + * + * Test interface to the fcntl system call. + * It will loop if the LOCK_NB flags is NOT set. + ***********************************************************************/ +int +record_lock(fd, flags, start, len, errormsg) +int fd; +int flags; +int start; +int len; +char **errormsg; +{ + register int cmd, ret; + struct flock flocks; + + memset(&flocks, 0, sizeof(struct flock)); + + if (flags&LOCK_NB) + cmd = F_SETLK; + else + cmd = F_SETLKW; + + flocks.l_whence = 0; + flocks.l_start = start; + flocks.l_len = len; + + if (flags&LOCK_UN) + flocks.l_type = F_UNLCK; + else if (flags&LOCK_EX) + flocks.l_type = F_WRLCK; + else if (flags&LOCK_SH) + flocks.l_type = F_RDLCK; + else { + errno = EINVAL; + if (errormsg != NULL) { + sprintf(errmsg, + "Programmer error, called record_lock with in valid flags\n"); + *errormsg = errmsg; + } + return -1; + } + + sprintf(Fl_syscall_str, + "fcntl(%d, %d, &flocks): type:%d whence:%d, start:%lld len:%lld\n", + fd, cmd, flocks.l_type, flocks.l_whence, + (long long)flocks.l_start, (long long)flocks.l_len); + + while (1) { + ret = fcntl(fd, cmd, &flocks); + + if (ret < 0) { + if (cmd == F_SETLK) + switch (errno) { + /* these errors are okay */ + case EACCES: /* Permission denied */ + case EINTR: /* interrupted system call */ +#ifdef EFILESH + case EFILESH: /* file shared */ +#endif + case EFSEXCLWR: /* File is write protected */ + continue; /* retry getting lock */ + } + if (errormsg != NULL) { + sprintf(errmsg, "fcntl(%d, %d, &flocks): errno:%d %s\n", + fd, cmd, errno, strerror(errno)); + *errormsg = errmsg; + } + return -1; + } + break; + } + + return ret; + +} /* end of record_lock */ + diff --git a/ltp_framework/lib/forker.c b/ltp_framework/lib/forker.c new file mode 100644 index 0000000..ad8b4a7 --- /dev/null +++ b/ltp_framework/lib/forker.c @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +/************************************************************** + * + * OS Testing - Silicon Graphics, Inc. + * + * FUNCTION NAME : forker + * background + * + * FUNCTION TITLE : fork desired number of copies of the current process + * fork a process and return control to caller + * + * SYNOPSIS: + * int forker(ncopies, mode, prefix) + * int ncopies; + * int mode; + * char *prefix; + * + * int background(prefix); + * char *prefix; + * + * AUTHOR : Richard Logan + * + * CO-PILOT(s) : Dean Roehrich + * + * INITIAL RELEASE : UNICOS 8.0 + * + * DESIGN DESCRIPTION + * The background function will do a fork of the current process. + * The parent process will then exit, thus orphaning the + * child process. Doing this will not nice the child process + * like executing a cmd in the background using "&" from the shell. + * If the fork fails and prefix is not NULL, a error message is printed + * to stderr and the process will exit with a value of errno. + * + * The forker function will fork minus one copies + * of the current process. There are two modes in how the forks + * will be done. Mode 0 (default) will have all new processes + * be childern of the parent process. Using Mode 1, + * the parent process will have one child and that child will + * fork the next process, if necessary, and on and on. + * The forker function will return the number of successful + * forks. This value will be different for the parent and each child. + * Using mode 0, the parent will get the total number of successful + * forks. Using mode 1, the newest child will get the total number + * of forks. The parent will get a return value of 1. + * + * The forker function also updates the global variables + * Forker_pids[] and Forker_npids. The Forker_pids array will + * be updated to contain the pid of each new process. The + * Forker_npids variable contains the number of entries + * in Forker_pids. Note, not all processes will have + * access to all pids via Forker_pids. If using mode 0, only the + * parent process and the last process will have all information. + * If using mode 1, only the last child process will have all information. + * + * If the prefix parameter is not NULL and the fork system call fails, + * a error message will be printed to stderr. The error message + * the be preceeded with prefix string. If prefix is NULL, + * no error message is printed. + * + * SPECIAL REQUIREMENTS + * None. + * + * UPDATE HISTORY + * This should contain the description, author, and date of any + * "interesting" modifications (i.e. info should helpful in + * maintaining/enhancing this module). + * username description + * ---------------------------------------------------------------- + * rrl This functions will first written during + * the SFS testing days, 1993. + * + * BUGS/LIMITATIONS + * The child pids are stored in the fixed array, Forker_pids. + * The array only has space for 4098 pids. Only the first + * 4098 pids will be stored in the array. + * + **************************************************************/ + +#include +#include +#include /* fork, getpid, sleep */ +#include +#include /* exit */ +#include "forker.h" + +int Forker_pids[FORKER_MAX_PIDS]; /* holds pids of forked processes */ +int Forker_npids=0; /* number of entries in Forker_pids */ + +/*********************************************************************** + * + * This function will fork and the parent will exit zero and + * the child will return. This will orphan the returning process + * putting it in the background. + * + * Return Value + * 0 : if fork did not fail + * !0 : if fork failed, the return value will be the errno. + ***********************************************************************/ +int +background(prefix) +char *prefix; +{ + switch (fork()) { + case -1: + if (prefix != NULL) + fprintf(stderr, "%s: In %s background(), fork() failed, errno:%d %s\n", + prefix, __FILE__, errno, strerror(errno)); + exit(errno); + + case 0: /* child process */ + break; + + default: + exit(0); + } + + return 0; + +} /* end of background */ + +/*********************************************************************** + * Forker will fork ncopies-1 copies of self. + * + ***********************************************************************/ +int +forker(ncopies, mode, prefix) +int ncopies; +int mode; /* 0 - all childern of parent, 1 - only 1 direct child */ +char *prefix; /* if ! NULL, an message will be printed to stderr */ + /* if fork fails. The prefix (program name) will */ + /* preceed the message */ +{ + int cnt; + int pid; + static int ind = 0; + + Forker_pids[ind]=0; + + for (cnt=1; cnt < ncopies; cnt++) { + + switch ( mode ) { + case 1 : /* only 1 direct child */ + if ((pid = fork()) == -1) { + if (prefix != NULL) + fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n", + prefix, __FILE__, errno, strerror(errno)); + return 0; + } + Forker_npids++; + + switch (pid ) { + case 0: /* child - continues the forking */ + + if (Forker_npids < FORKER_MAX_PIDS) + Forker_pids[Forker_npids-1]=getpid(); + break; + + default: /* parent - stop the forking */ + if (Forker_npids < FORKER_MAX_PIDS) + Forker_pids[Forker_npids-1]=pid; + return cnt-1; + } + + break; + + default : /* all new processes are childern of parent */ + if ((pid = fork()) == -1) { + if (prefix != NULL) + fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n", + prefix, __FILE__, errno, strerror(errno)); + return cnt-1; + } + Forker_npids++; + + switch (pid ) { + case 0: /* child - stops the forking */ + if (Forker_npids < FORKER_MAX_PIDS) + Forker_pids[Forker_npids-1]=getpid(); + return cnt; + + default: /* parent - continues the forking */ + if (Forker_npids < FORKER_MAX_PIDS) + Forker_pids[Forker_npids-1]=pid; + break; + } + break; + } + } + + if (Forker_npids < FORKER_MAX_PIDS) + Forker_pids[Forker_npids]=0; + return cnt-1; + +} /* end of forker */ + + +#if UNIT_TEST + +/* + * The following is a unit test main for the background and forker + * functions. + */ + +int +main(argc, argv) +int argc; +char **argv; +{ + int ncopies=1; + int mode=0; + int ret; + int ind; + + if (argc == 1) { + printf("Usage: %s ncopies [mode]\n", argv[0]); + exit(1); + } + + if (sscanf(argv[1], "%i", &ncopies) != 1) { + printf("%s: ncopies argument must be integer\n", argv[0]); + exit(1); + } + + if (argc == 3) + if (sscanf(argv[2], "%i", &mode) != 1) { + printf("%s: mode argument must be integer\n", argv[0]); + exit(1); + } + + printf("Starting Pid = %d\n", getpid()); + ret=background(argv[0]); + printf("After background() ret:%d, pid = %d\n", ret, getpid()); + + ret=forker(ncopies, mode, argv[0]); + + printf("forker(%d, %d, %s) ret:%d, pid = %d, sleeping 30 seconds.\n", + ncopies, mode, argv[0], ret, getpid()); + + printf("%d My version of Forker_pids[], Forker_npids = %d\n", + getpid(), Forker_npids); + + for (ind=0; ind + +char *get_high_address(void) +{ + return (char *)sbrk(0) + (4 * getpagesize()); +} \ No newline at end of file diff --git a/ltp_framework/lib/get_path.c b/ltp_framework/lib/get_path.c new file mode 100644 index 0000000..6501a06 --- /dev/null +++ b/ltp_framework/lib/get_path.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2010 Cyril Hrubis chrubis@suse.cz + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + */ + + /* + * Looks for binary prog_name in $PATH. + * + * If such file exists and if you are able at least to read it, zero is + * returned and absolute path to the file is filled into buf. In case buf is + * too short to hold the absolute path + prog_name for the file we are looking + * for -1 is returned as well as when there is no such file in all paths in + * $PATH. + */ + +#include "test.h" + +#include +#include +#include +#include +#include +#include + +#define MIN(a, b) ((a)<(b)?(a):(b)) + +static int file_exist(const char *path) +{ + struct stat st; + + if (!access(path, R_OK) && !stat(path, &st) && S_ISREG(st.st_mode)) + return 1; + + return 0; +} + +int tst_get_path(const char *prog_name, char *buf, size_t buf_len) +{ + const char *path = (const char*) getenv("PATH"); + const char *start = path; + const char *end; + size_t size, ret; + + + if (path == NULL) + return -1; + + do { + end = strchr(start, ':'); + + if (end != NULL) + snprintf(buf, MIN(buf_len, (size_t)(end - start + 1)), "%s", start); + else + snprintf(buf, buf_len, "%s", start); + + size = strlen(buf); + + /* + * "::" inside $PATH, $PATH ending with ':' or $PATH starting + * with ':' should be expanded into current working directory. + */ + if (size == 0) { + snprintf(buf, buf_len, "."); + size = strlen(buf); + } + + /* + * If there is no '/' ad the end of path from $PATH add it. + */ + if (buf[size - 1] != '/') + ret = snprintf(buf + size, buf_len - size, "/%s", prog_name); + else + ret = snprintf(buf + size, buf_len - size, "%s", prog_name); + + if (buf_len - size > ret && file_exist(buf)) + return 0; + + start = end + 1; + + } while (end != NULL); + + return -1; +} \ No newline at end of file diff --git a/ltp_framework/lib/libltp.a b/ltp_framework/lib/libltp.a new file mode 100644 index 0000000..6f969a4 Binary files /dev/null and b/ltp_framework/lib/libltp.a differ diff --git a/ltp_framework/lib/libtestsuite.c b/ltp_framework/lib/libtestsuite.c new file mode 100644 index 0000000..1703ff7 --- /dev/null +++ b/ltp_framework/lib/libtestsuite.c @@ -0,0 +1,164 @@ +/* + * + * Copyright (c) International Business Machines Corp., 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * NAME + * libtestsuite.c + * + * DESCRIPTION + * file containing generic routines which are used by some of the LTP + * testsuite tests. Currently, the following routines are present in + * this library: + * + * my_getpwnam(), do_file_setup() + * + * HISTORY + * 11/03/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com) + * - Add the following functions to synchronise father and sons processes + * sync_pipe_create(), sync_pipe_wait(), sync_pipe_notify() + */ +#include +#include +#include +#include +#include + +#include "libtestsuite.h" +#include "test.h" +#include "usctest.h" + +struct passwd * +my_getpwnam(char *name) +{ + struct passwd *saved_pwent; + struct passwd *pwent; + + if ((pwent = getpwnam(name)) == NULL) { + perror("getpwnam"); + tst_brkm(TBROK, NULL, "getpwnam() failed"); + } + saved_pwent = (struct passwd *)malloc(sizeof(struct passwd)); + + *saved_pwent = *pwent; + + return(saved_pwent); +} + +void +do_file_setup(char *fname) +{ + int fd; + + if ((fd = open(fname,O_RDWR|O_CREAT,0700)) == -1) { + tst_resm(TBROK, "open(%s, O_RDWR|O_CREAT,0700) Failed, " + "errno=%d : %s", fname, errno, strerror(errno)); + } + + if (close(fd) == -1) { + tst_resm(TWARN, "close(%s) Failed on file create, errno=%d : " + "%s", fname, errno, strerror(errno)); + } +} + +static char pipe_name[256]; + +void generate_pipe_name(const char *name) +{ + char *p; + + p = strrchr(name, '/'); + if (p == NULL) + p = (char *) name; + else + p++; + snprintf(pipe_name, 255, "%s/ltp_fifo_%s", P_tmpdir, p); +} + +int sync_pipe_create(int fd[], const char *name) +{ + int ret; + + if (name != NULL) { + generate_pipe_name(name); + + ret = open(pipe_name, O_RDWR); + if (ret != -1) { + fd[0] = ret; + fd[1] = open(pipe_name, O_RDWR); + } else { + ret = mkfifo(pipe_name, S_IRWXU); + if (!ret) { + fd[0] = open(pipe_name, O_RDWR); + fd[1] = open(pipe_name, O_RDWR); + } + } + return ret; + } else + return pipe(fd); +} + +int sync_pipe_close(int fd[], const char *name) +{ + int r = 0; + + if (fd[0] != -1) + r = close (fd[0]); + if (fd[1] != -1) + r |= close (fd[1]); + + if (name != NULL) { + generate_pipe_name(name); + unlink(pipe_name); + } + return r; +} + +int sync_pipe_wait(int fd[]) +{ + char buf; + int r; + + if (fd[1] != -1) { + close (fd[1]); + fd[1] = -1; + } + + r = read (fd[0], &buf, 1); + + if ((r != 1) || (buf != 'A')) + return -1; + return 0; +} + +int sync_pipe_notify(int fd[]) +{ + char buf = 'A'; + int r; + + if (fd[0] != -1) { + close (fd[0]); + fd[0] = -1; + } + + r = write (fd[1], &buf, 1); + + if (r != 1) + return -1; + return 0; +} \ No newline at end of file diff --git a/ltp_framework/lib/ltp.pc b/ltp_framework/lib/ltp.pc new file mode 100644 index 0000000..5c4c042 --- /dev/null +++ b/ltp_framework/lib/ltp.pc @@ -0,0 +1,10 @@ +prefix=/opt/ltp +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +Name: LTP +Description: Linux Test Project +Version: LTP_VERSION +Libs: -L${libdir} -lltp +Cflags: -I${includedir} diff --git a/ltp_framework/lib/ltp.pc.in b/ltp_framework/lib/ltp.pc.in new file mode 100644 index 0000000..9620129 --- /dev/null +++ b/ltp_framework/lib/ltp.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +includedir=@includedir@ +libdir=@libdir@ + +Name: LTP +Description: Linux Test Project +Version: @VERSION@ +Libs: -L${libdir} -lltp +Cflags: -I${includedir} diff --git a/ltp_framework/lib/mount_utils.c b/ltp_framework/lib/mount_utils.c new file mode 100644 index 0000000..5a9fd8c --- /dev/null +++ b/ltp_framework/lib/mount_utils.c @@ -0,0 +1,213 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Return the block device for a given path. You must free the string after you + * call this function. + * + * Returns NULL if the device isn't found, memory couldn't be allocated, or if + * the `block device' isn't a real block device (e.g. nfs mounts, etc). + */ +char * +get_block_device(const char *path) +{ + + char *mnt_dir = NULL, *mnt_fsname = NULL; + char *resolved_path = NULL; + FILE *mtab_f; + int done = 0; + struct mntent *entry; + struct stat junk; + + if (path == NULL) { + errno = EINVAL; + } else if ((resolved_path = realpath(path, NULL)) != NULL && + (mtab_f = setmntent("/etc/mtab", "r")) != NULL) + { + + do { + + entry = getmntent(mtab_f); + + if (entry != NULL) { + + if (!strncmp(entry->mnt_dir, resolved_path, strlen(entry->mnt_dir))) { + + char copy_string = 0; + + if (mnt_dir == NULL) { + + mnt_dir = malloc(strlen(entry->mnt_dir)+1); + mnt_fsname = malloc(strlen(entry->mnt_fsname)+1); + + copy_string = mnt_dir != NULL && mnt_fsname != NULL; + + } else { + + if (!strncmp(entry->mnt_dir, mnt_dir, strlen(entry->mnt_dir))) { + + mnt_dir = realloc(mnt_dir, strlen(entry->mnt_dir)); + mnt_fsname = realloc(mnt_fsname, strlen(entry->mnt_fsname)); + copy_string = 1; + + } + + } + + if (copy_string != 0) { + strcpy(mnt_dir, entry->mnt_dir); + strcpy(mnt_fsname, entry->mnt_fsname); +#if DEBUG + printf("%s is a subset of %s\n", path, entry->mnt_dir); + } else { + printf("%s is not a subset of %s\n", path, entry->mnt_dir); +#endif + } + +#if DEBUG + } else { + printf("%s is not a subset of %s\n", path, entry->mnt_dir); +#endif + } + + } + + } while (done == 0 && entry != NULL); + + endmntent(mtab_f); + + } + + if (mnt_dir != NULL) { + free(mnt_dir); + } + if (resolved_path != NULL) { + free(resolved_path); + } + + if (mnt_fsname != NULL && stat(mnt_fsname, &junk) < 0 && + errno == ENOENT) { + free(mnt_fsname); + mnt_fsname = NULL; + errno = ENODEV; + } + + return mnt_fsname; + +} + +/* + * Return the mountpoint for a given path. You must free the string after you + * call this function. + * + * Returns NULL if memory couldn't be allocated. + */ +char * +get_mountpoint(const char *path) +{ + + char *mnt_dir = NULL; + char *resolved_path = NULL; + FILE *mtab_f; + int done = 0; + struct mntent *entry; + + if (path == NULL) { + errno = EINVAL; + } else if ((resolved_path = realpath(path, NULL)) != NULL && + (mtab_f = setmntent("/etc/mtab", "r")) != NULL) + { + + do { + + entry = getmntent(mtab_f); + + if (entry != NULL) { + + if (!strncmp(entry->mnt_dir, resolved_path, strlen(entry->mnt_dir))) { + + char copy_string = 0; + + if (mnt_dir == NULL) { + + mnt_dir = malloc(strlen(entry->mnt_dir)+1); + copy_string = mnt_dir != NULL; + + } else { + + if (!strncmp(entry->mnt_dir, mnt_dir, strlen(entry->mnt_dir))) { + + mnt_dir = realloc(mnt_dir, strlen(entry->mnt_dir)); + copy_string = 1; + + } + + } + + if (copy_string != 0) { + strcpy(mnt_dir, entry->mnt_dir); +#if DEBUG + printf("%s is a subset of %s\n", path, entry->mnt_dir); + } else { + printf("%s is not a subset of %s\n", path, entry->mnt_dir); +#endif + } + +#if DEBUG + } else { + printf("%s is not a subset of %s\n", path, entry->mnt_dir); +#endif + } + + } + + } while (done == 0 && entry != NULL); + + endmntent(mtab_f); + + } + + if (resolved_path != NULL) { + free(resolved_path); + } + + return mnt_dir; + +} +#if UNIT_TEST +int +main(void) +{ + + char *mnt_fsname; + char *paths[] = { + "/home", + "/mnt", + "/tmp/foo", /* mkdir /tmp/foo; mount -t tmpfs none /tmp/foo/ */ + "/proc", + "/optimus/store" + }; + int i; + + for (i = 0; i < sizeof(paths) / sizeof(*paths); i++) { + mnt_fsname = get_block_device(paths[i]); + printf("%s - %s\n", paths[i], mnt_fsname); + if (mnt_fsname != NULL) { + free(mnt_fsname); + mnt_fsname = NULL; + } + } + + return 0; + +} +#endif \ No newline at end of file diff --git a/ltp_framework/lib/open_flags.c b/ltp_framework/lib/open_flags.c new file mode 100644 index 0000000..5623382 --- /dev/null +++ b/ltp_framework/lib/open_flags.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +/************************************************************** + * + * OS Testing - Silicon Graphics, Inc. + * + * FUNCTION NAME : parse_open_flags + * openflags2symbols + * + * FUNCTION TITLE : converts open flag symbols into bitmask + * converts open flag bitmask into symbols + * + * SYNOPSIS: + * int parse_open_flags(symbols, badname) + * char *symbols; + * char **badname; + * + * char *openflags2symbols(openflags, sep, mode) + * int openflags; + * char *sep; + * int mode; + * + * AUTHOR : Richard Logan + * + * CO-PILOT(s) : Dean Roehrich + * + * INITIAL RELEASE : UNICOS 8.0 + * + * DESIGN DESCRIPTION + * The parse_open_flags function can be used to convert + * a list of comma separated open(2) flag symbols (i.e. O_TRUNC) + * into the bitmask that can be used by open(2). + * If a symbol is unknown and is not NULL, + * will updated to point that symbol in . + * Parse_open_flags will return -1 on this error. + * Otherwise parse_open_flags will return the open flag bitmask. + * If parse_open_flags returns, will left unchanged. + * + * The openflags2symbols function attempts to convert open flag + * bits into human readable symbols (i.e. O_TRUNC). If there + * are more than one symbol, the string will be placed as + * a separator between symbols. Commonly used separators would + * be a comma "," or pipe "|". If is one and not all + * bits can be converted to symbols, the "UNKNOWN" + * symbol will be added to return string. + * Openflags2symbols will return the indentified symbols. + * If no symbols are recognized the return value will be a empty + * string or the "UNKNOWN" symbol. + * + * SPECIAL REQUIREMENTS + * None. + * + * UPDATE HISTORY + * This should contain the description, author, and date of any + * "interesting" modifications (i.e. info should helpful in + * maintaining/enhancing this module). + * username description + * ---------------------------------------------------------------- + * rrl This code was first created during the beginning + * of the SFS testing days. I think that was in 1993. + * This code was updated in 05/96. + * (05/96) openflags2symbols was written. + * + * BUGS/LIMITATIONS + * Currently (05/96) all known symbols are coded into openflags2symbols. + * If new open flags are added this code will have to updated + * to know about them or they will not be recognized. + * + **************************************************************/ + +#include +#include +#include +#include +#include /* strcat */ +#include "open_flags.h" + +#define UNKNOWN_SYMBOL "UNKNOWN" + +static char Open_symbols[512]; /* space for openflags2symbols return value */ + +struct open_flag_t { + char *symbol; + int flag; +}; + +static struct open_flag_t Open_flags[] = { + { "O_RDONLY", O_RDONLY }, + { "O_WRONLY", O_WRONLY }, + { "O_RDWR", O_RDWR }, + { "O_SYNC", O_SYNC }, + { "O_CREAT", O_CREAT }, + { "O_TRUNC", O_TRUNC }, + { "O_EXCL", O_EXCL }, + { "O_APPEND", O_APPEND }, + { "O_NONBLOCK", O_NONBLOCK }, +#if O_NOCTTY + { "O_NOCTTY", O_NOCTTY }, +#endif +#if O_DSYNC + { "O_DSYNC", O_DSYNC }, +#endif +#if O_RSYNC + { "O_RSYNC", O_RSYNC }, +#endif +#if O_ASYNC + { "O_ASYNC", O_ASYNC }, +#endif +#if O_PTYIGN + { "O_PTYIGN", O_PTYIGN }, +#endif +#if O_NDELAY + { "O_NDELAY", O_NDELAY }, +#endif +#if O_RAW + { "O_RAW", O_RAW }, +#endif +#ifdef O_SSD + { "O_SSD", O_SSD }, +#endif +#if O_BIG + { "O_BIG", O_BIG }, +#endif +#if O_PLACE + { "O_PLACE", O_PLACE }, +#endif +#if O_RESTART + { "O_RESTART", O_RESTART }, +#endif +#if O_SFSXOP + { "O_SFSXOP", O_SFSXOP }, +#endif +#if O_SFS_DEFER_TM + { "O_SFS_DEFER_TM", O_SFS_DEFER_TM }, +#endif +#if O_WELLFORMED + { "O_WELLFORMED", O_WELLFORMED }, +#endif +#if O_LDRAW + { "O_LDRAW", O_LDRAW }, +#endif +#if O_T3D + { "O_T3D", O_T3D }, +#endif /* O_T3D */ +#if O_PARALLEL + { "O_PARALLEL", O_PARALLEL }, + { "O_FSA", O_PARALLEL|O_WELLFORMED|O_RAW }, /* short cut */ +#endif /* O_PARALLEL */ +#ifdef O_LARGEFILE + { "O_LARGEFILE", O_LARGEFILE }, +#endif +#ifdef O_DIRECT + { "O_DIRECT", O_DIRECT }, +#endif +#ifdef O_PRIV + { "O_PRIV", O_PRIV }, +#endif + +}; + +int +parse_open_flags(char *string, char **badname) +{ + int bits = 0; + char *name; + char *cc; + char savecc; + int found; + unsigned int ind; + + name=string; + cc=name; + + while ( 1 ) { + + for (; ((*cc != ',') && (*cc != '\0')); cc++); + savecc = *cc; + *cc = '\0'; + + found = 0; + + for (ind=0; ind < sizeof(Open_flags)/sizeof(struct open_flag_t); ind++) { + if (strcmp(name, Open_flags[ind].symbol) == 0) { + bits |= Open_flags[ind].flag; + found=1; + break; + } + } + + *cc = savecc; /* restore string */ + + if (found == 0) { /* invalid name */ + if (badname != NULL) + *badname = name; + return -1; + } + + if (savecc == '\0') + break; + + name = ++cc; + + } /* end while */ + + return bits; + +} /* end of parse_open_flags */ + + +char * +openflags2symbols(int openflags, char *sep, int mode) +{ + int ind; + int size; + int bits = openflags; + int havesome=0; + + Open_symbols[0]='\0'; + + size=sizeof(Open_flags)/sizeof(struct open_flag_t); + + /* + * Deal with special case of O_RDONLY. If O_WRONLY nor O_RDWR + * bits are not set, assume O_RDONLY. + */ + + if ((bits & (O_WRONLY | O_RDWR)) == 0) { + strcat(Open_symbols, "O_RDONLY"); + havesome=1; + } + + /* + * Loop through all but O_RDONLY elments of Open_flags + */ + for (ind=1; ind < size; ind++) { + + if ((bits & Open_flags[ind].flag) == Open_flags[ind].flag) { + if (havesome) + strcat(Open_symbols, sep); + + strcat(Open_symbols, Open_flags[ind].symbol); + havesome++; + + /* remove flag bits from bits */ + bits = bits & (~Open_flags[ind].flag); + } + } + + /* + * If not all bits were identified and mode was equal to 1, + * added UNKNOWN_SYMBOL to return string + */ + if (bits && mode == 1) { /* not all bits were identified */ + if (havesome) + strcat(Open_symbols, sep); + strcat(Open_symbols, UNKNOWN_SYMBOL); + } + + return Open_symbols; + +} /* end of openflags2symbols */ + + +#ifdef UNIT_TEST + +/* + * The following code provides a UNIT test main for + * parse_open_flags and openflags2symbols functions. + */ + +int +main(argc, argv) +int argc; +char **argv; +{ + int bits; + int ret; + char *err; + + if (argc == 1) { + printf("Usage: %s openflagsbits\n\t%s symbols\n", argv[0], argv[0]); + exit(1); + } + + if (sscanf(argv[1], "%i", &bits) == 1) { + printf("openflags2symbols(%#o, \",\", 1) returned %s\n", + bits, openflags2symbols(bits, ",", 1)); + + } else { + ret=parse_open_flags(argv[1], &err); + if (ret == -1) + printf("parse_open_flags(%s, &err) returned -1, err = %s\n", + argv[0], err); + else + printf("parse_open_flags(%s, &err) returned %#o\n", argv[0], ret); + } + + exit(0); +} + +#endif /* end of UNIT_TEST */ \ No newline at end of file diff --git a/ltp_framework/lib/parse_opts.c b/ltp_framework/lib/parse_opts.c new file mode 100644 index 0000000..358106e --- /dev/null +++ b/ltp_framework/lib/parse_opts.c @@ -0,0 +1,879 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ + +/* $Id: parse_opts.c,v 1.14 2009/08/28 09:59:52 vapier Exp $ */ + +/********************************************************** + * + * OS Testing - Silicon Graphics, Inc. + * + * FUNCTION NAME : parse_opts + * + * FUNCTION TITLE : parse standard & user options for system call tests + * + * SYNOPSIS: + * #include "usctest.h" + * + * char *parse_opts(ac, av, user_optarr, uhf) + * int ac; + * char **av; + * option_t user_optarr[]; + * void (*uhf)(); + * + * AUTHOR : William Roske/Richard Logan + * + * INITIAL RELEASE : UNICOS 7.0 + * + * DESCRIPTION + * The parse_opts library routine takes that argc and argv parameters + * recevied by main() and an array of structures defining user options. + * It parses the command line setting flag and argument locations + * associated with the options. It uses getopt to do the actual cmd line + * parsing. uhf() is a function to print user define help + * + * This module contains the functions usc_global_setup_hook and + * usc_test_looping, which are called by marcos defined in usctest.h. + * + * RETURN VALUE + * parse_opts returns a pointer to an error message if an error occurs. + * This pointer is (char *)NULL if parsing is successful. + * + *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +#if UNIT_TEST +#include +#endif /* UNIT_TEST */ + +#include "test.h" +#define _USC_LIB_ 1 /* indicates we are the library to the usctest.h include */ +#include "usctest.h" + +#ifndef USC_COPIES +#define USC_COPIES "USC_COPIES" +#endif + +#ifndef UNIT_TEST +#define UNIT_TEST 0 +#endif + +#ifndef DEBUG +#define DEBUG 0 +#endif + +/* The timing information block. */ +struct tblock tblock={0,((long) -1)>>1,0,0}; + +#ifdef GARRETT_IS_A_PEDANTIC_BASTARD +extern pid_t spawned_program_pid; +#endif + +/* Define flags and args for standard options */ +int STD_FUNCTIONAL_TEST=1, /* flag indicating to do functional testing code */ + STD_TIMING_ON=0, /* flag indicating to print timing stats */ + STD_PAUSE=0, /* flag indicating to pause before actual start, */ + /* for contention mode */ + STD_INFINITE=0, /* flag indciating to loop forever */ + STD_LOOP_COUNT=1, /* number of iterations */ + STD_COPIES=1, /* number of copies */ + STD_ERRNO_LOG=0; /* flag indicating to do errno logging */ + +float STD_LOOP_DURATION=0.0, /* duration value in fractional seconds */ + STD_LOOP_DELAY=0.0; /* loop delay value in fractional seconds */ + + +char **STD_opt_arr = NULL; /* array of option strings */ +int STD_nopts=0, /* number of elements in STD_opt_arr */ + STD_argind=1; /* argv index to next argv element */ + /* (first argument) */ + /* To getopt users, it is like optind */ + +/* + * The following variables are to support system testing additions. + */ +static int STD_TP_barrier=0; /* flag to do barrier in TEST_PAUSE */ + /* 2 - wait_barrier(), 3 - set_barrier(), * - barrier() */ +static int STD_LP_barrier=0; /* flag to do barrier in TEST_LOOPING */ + /* 2 - wait_barrier(), 3 - set_barrier(), * - barrier() */ +static int STD_TP_shmem_sz=0; /* shmalloc this many words per pe in TEST_PAUSE */ +static int STD_LD_shmem=0; /* flag to do shmem_puts and shmem_gets during delay */ +static int STD_LP_shmem=0; /* flag to do shmem_puts and gets during TEST_LOOPING */ +static int STD_LD_recfun=0; /* do recressive function calls in loop delay */ +static int STD_LP_recfun=0; /* do recressive function calls in TEST_LOOPING */ +static int STD_TP_sbrk=0; /* do sbrk in TEST_PAUSE */ +static int STD_LP_sbrk=0; /* do sbrk in TEST_LOOPING */ +static char *STD_start_break=0; /* original sbrk size */ +static int Debug=0; + +struct std_option_t { + char *optstr; + char *help; + char *flag; + char **arg; +} std_options[] = { + { "c:", " -c n Run n copies concurrently\n", NULL, NULL}, + { "e" , " -e Turn on errno logging\n", NULL, NULL}, + { "f" , " -f Turn off functional testing\n", NULL, NULL}, + { "h" , " -h Show this help screen\n", NULL, NULL}, + { "i:", " -i n Execute test n times\n", NULL, NULL}, + { "I:", " -I x Execute test for x seconds\n", NULL, NULL}, + { "p" , " -p Pause for SIGUSR1 before starting\n", NULL, NULL}, + { "P:", " -P x Pause for x seconds between iterations\n", NULL, NULL}, + { "t" , " -t Turn on syscall timing\n", NULL, NULL}, +#ifdef UCLINUX + { "C:", " -C ARG Run the child process with arguments ARG (for internal use)\n", + NULL, NULL}, +#endif + {NULL, NULL, NULL, NULL}}; + +void print_help(void (*user_help)()); + +/* + * Structure for usc_recressive_func argument + */ +struct usc_bigstack_t { + char space[4096]; +}; + +static struct usc_bigstack_t *STD_bigstack=NULL; + +/* + * Counter of errnos returned (-e option). Indexed by errno. + * Make the array USC_MAX_ERRNO long. That is the first Fortran + * Lib errno. No syscall should return an errno that high. + */ +int STD_ERRNO_LIST[USC_MAX_ERRNO]; + +/* define the string length for Mesg and Mesg2 strings */ +#define STRLEN 2048 + +static char Mesg2[STRLEN]; /* holds possible return string */ +static void usc_recressive_func(); + +/* + * Define bits for options that might have env variable default + */ +#define OPT_iteration 01 +#define OPT_nofunccheck 02 +#define OPT_duration 04 +#define OPT_delay 010 +#define OPT_copies 020 + +#ifdef UCLINUX +/* Allocated and used in self_exec.c: */ +extern char *child_args; /* Arguments to child when -C is used */ +#endif + +/********************************************************************** + * parse_opts: + **********************************************************************/ +char * +parse_opts(int ac, char **av, const option_t *user_optarr, void (*uhf)()) +{ + int found; /* flag to indicate that an option specified was */ + /* found in the user's list */ + int k; /* scratch integer for returns and short time usage */ + float ftmp; /* tmp float for parsing env variables */ + char *ptr; /* used in getting env variables */ + int options=0; /* no options specified */ + int optstrlen, i; + char *optionstr; + int opt; /* return of getopt */ + + /* + * If not the first time this function is called, release the old STD_opt_arr + * vector. + */ + +#ifdef GARRETT_IS_A_PEDANTIC_BASTARD + spawned_program_pid = getpid(); +#endif + + if (STD_opt_arr != NULL) { + free(STD_opt_arr); + STD_opt_arr = NULL; + } + /* Calculate how much space we need for the option string */ + optstrlen = 0; + for (i = 0; std_options[i].optstr; ++i) + optstrlen += strlen(std_options[i].optstr); + if (user_optarr) + for (i = 0; user_optarr[i].option; ++i) { + if (strlen(user_optarr[i].option) > 2) + return "parse_opts: ERROR - Only short options are allowed"; + optstrlen += strlen(user_optarr[i].option); + } + optstrlen += 1; + + /* Create the option string for getopt */ + optionstr = malloc(optstrlen); + if (!optionstr) + return "parse_opts: ERROR - Could not allocate memory for optionstr"; + + optionstr[0] = '\0'; + + for (i = 0; std_options[i].optstr; ++i) + strcat(optionstr, std_options[i].optstr); + if (user_optarr) + for (i = 0; user_optarr[i].option; ++i) + /* only add the option if it wasn't there already */ + if (strchr(optionstr, user_optarr[i].option[0]) == NULL) + strcat(optionstr, user_optarr[i].option); + +#if DEBUG > 1 + printf("STD_nopts = %d\n", STD_nopts); +#endif + + /* + * Loop through av parsing options. + */ + while ((opt = getopt(ac, av, optionstr)) > 0) { + + STD_argind = optind; +#if DEBUG > 0 + printf("parse_opts: getopt returned '%c'\n", opt); +#endif + + switch (opt) { + case '?': /* Unknown option */ + return "Unknown option"; + break; + case ':': /* Missing Arg */ + return "Missing argument"; + break; + case 'i': /* Iterations */ + options |= OPT_iteration; + STD_LOOP_COUNT = atoi(optarg); + if (STD_LOOP_COUNT == 0) STD_INFINITE = 1; + break; + case 'P': /* Delay between iterations */ + options |= OPT_delay; + STD_LOOP_DELAY = atof(optarg); + break; + case 'I': /* Time duration */ + options |= OPT_duration; + STD_LOOP_DURATION = atof(optarg); + if (STD_LOOP_DURATION == 0.0) STD_INFINITE=1; + break; + case 'c': /* Copies */ + options |= OPT_copies; + STD_COPIES = atoi(optarg); + break; + case 'f': /* Functional testing */ + STD_FUNCTIONAL_TEST = 0; + break; + case 'p': /* Pause for SIGUSR1 */ + STD_PAUSE = 1; + break; + case 't': /* syscall timing */ + STD_TIMING_ON = 1; + break; + case 'e': /* errno loggin */ + STD_ERRNO_LOG = 1; + break; + case 'h': /* Help */ + print_help(uhf); + exit(0); + break; +#ifdef UCLINUX + case 'C': /* Run child */ + child_args = optarg; + break; +#endif + default: + + /* Check all the user specified options */ + found=0; + for (i = 0; user_optarr[i].option; ++i) { + + if (opt == user_optarr[i].option[0]) { + /* Yup, This is a user option, set the flag and look for argument */ + if (user_optarr[i].flag) { + *user_optarr[i].flag=1; + } + found++; + + /* save the argument at the user's location */ + if (user_optarr[i].option[strlen(user_optarr[i].option)-1] == ':') { + *user_optarr[i].arg = optarg; + } + break; /* option found - break out of the for loop */ + } + } + /* This condition "should never happen". SO CHECK FOR IT!!!! */ + if (!found) { + sprintf(Mesg2, + "parse_opts: ERROR - option:\"%c\" NOT FOUND... INTERNAL " + "ERROR", opt); + return(Mesg2); + } + } + + } /* end of while */ + free(optionstr); + + STD_argind = optind; + + /* + * Turn on debug + */ + if ((ptr = getenv("USC_DEBUG")) != NULL) { + Debug = 1; + printf("env USC_DEBUG is defined, turning on debug\n"); + } + if ((ptr = getenv("USC_VERBOSE")) != NULL) { + Debug = 1; + printf("env USC_VERBOSE is defined, turning on debug\n"); + } + + /* + * If the USC_ITERATION_ENV environmental variable is set to + * a number, use that number as iteration count (same as -c option). + * The -c option with arg will be used even if this env var is set. + */ + if (!(options & OPT_iteration) && (ptr = getenv(USC_ITERATION_ENV)) != NULL) { + if (sscanf(ptr, "%i", &k) == 1) { + if (k == 0) { /* if arg is 0, set infinite loop flag */ + STD_INFINITE = 1; + if (Debug) + printf("Using env %s, set STD_INFINITE to 1\n", + USC_ITERATION_ENV); + } else { /* else, set the loop count to the arguement */ + STD_LOOP_COUNT=k; + if (Debug) + printf("Using env %s, set STD_LOOP_COUNT to %d\n", + USC_ITERATION_ENV, k); + } + } + } + + /* + * If the USC_NO_FUNC_CHECK environmental variable is set, we'll + * unset the STD_FUNCTIONAL_TEST variable. + */ + if (!(options & OPT_nofunccheck) && + (ptr = getenv(USC_NO_FUNC_CHECK)) != NULL) { + STD_FUNCTIONAL_TEST=0; /* Turn off functional testing */ + if (Debug) + printf("Using env %s, set STD_FUNCTIONAL_TEST to 0\n", + USC_NO_FUNC_CHECK); + } + + /* + * If the USC_LOOP_WALLTIME environmental variable is set, + * use that number as duration (same as -I option). + * The -I option with arg will be used even if this env var is set. + */ + + if (!(options & OPT_duration) && + (ptr = getenv(USC_LOOP_WALLTIME)) != NULL) { + if (sscanf(ptr, "%f", &ftmp) == 1 && ftmp >= 0.0) { + STD_LOOP_DURATION = ftmp; + if (Debug) + printf("Using env %s, set STD_LOOP_DURATION to %f\n", + USC_LOOP_WALLTIME, ftmp); + if (STD_LOOP_DURATION == 0.0) { /* if arg is 0, set infinite loop flag */ + STD_INFINITE = 1; + if (Debug) + printf("Using env %s, set STD_INFINITE to 1\n", USC_LOOP_WALLTIME); + } + } + } + if (!(options & OPT_duration) && (ptr = getenv("USC_DURATION")) != NULL) { + if (sscanf(ptr, "%f", &ftmp) == 1 && ftmp >= 0.0) { + STD_LOOP_DURATION = ftmp; + if (Debug) + printf("Using env USC_DURATION, set STD_LOOP_DURATION to %f\n", ftmp); + if (STD_LOOP_DURATION == 0.0) { /* if arg is 0, set infinite loop flag */ + STD_INFINITE = 1; + if (Debug) + printf("Using env USC_DURATION, set STD_INFINITE to 1\n"); + } + } + } + /* + * If the USC_LOOP_DELAY environmental variable is set, + * use that number as delay in factional seconds (same as -P option). + * The -P option with arg will be used even if this env var is set. + */ + if (!(options & OPT_delay) && (ptr = getenv(USC_LOOP_DELAY)) != NULL) { + if (sscanf(ptr, "%f", &ftmp) == 1 && ftmp >= 0.0) { + STD_LOOP_DELAY = ftmp; + if (Debug) + printf("Using env %s, set STD_LOOP_DELAY = %f\n", + USC_LOOP_DELAY, ftmp); + } + } + + /* + * If the USC_COPIES environmental variable is set, + * use that number as copies (same as -c option). + * The -c option with arg will be used even if this env var is set. + */ + if (!(options & OPT_copies) && (ptr = getenv(USC_COPIES)) != NULL) { + if (sscanf(ptr, "%d", &STD_COPIES) == 1 && STD_COPIES >= 0) { + if (Debug) + printf("Using env %s, set STD_COPIES = %d\n", + USC_COPIES, STD_COPIES); + } + } + + /* + * The following are special system testing envs to turn on special + * hooks in the code. + */ + if ((ptr = getenv("USC_TP_BARRIER")) != NULL) { + if (sscanf(ptr, "%i", &k) == 1 && k >= 0) + STD_TP_barrier=k; + else + STD_TP_barrier=1; + if (Debug) + printf("using env USC_TP_BARRIER, Set STD_TP_barrier to %d\n", + STD_TP_barrier); + } + + if ((ptr = getenv("USC_LP_BARRIER")) != NULL) { + if (sscanf(ptr, "%i", &k) == 1 && k >= 0) + STD_LP_barrier=k; + else + STD_LP_barrier=1; + if (Debug) + printf("using env USC_LP_BARRIER, Set STD_LP_barrier to %d\n", + STD_LP_barrier); + } + + if ((ptr = getenv("USC_TP_SHMEM")) != NULL) { + if (sscanf(ptr, "%i", &k) == 1 && k >= 0) { + STD_TP_shmem_sz=k; + if (Debug) + printf("Using env USC_TP_SHMEM, Set STD_TP_shmem_sz to %d\n", + STD_TP_shmem_sz); + } + } + + if ((ptr = getenv("USC_LP_SHMEM")) != NULL) { + if (sscanf(ptr, "%i", &k) == 1 && k >= 0) { + STD_LP_shmem=k; + if (Debug) + printf("Using env USC_LP_SHMEM, Set STD_LP_shmem to %d\n", + STD_LP_shmem); + } + } + + if ((ptr = getenv("USC_LD_SHMEM")) != NULL) { + if (sscanf(ptr, "%i", &k) == 1 && k >= 0) { + STD_LD_shmem=k; + if (Debug) + printf("Using env USC_LD_SHMEM, Set STD_LD_shmem to %d\n", + STD_LD_shmem); + } + } + + if ((ptr = getenv("USC_TP_SBRK")) != NULL) { + if (sscanf(ptr, "%i", &k) == 1 && k >= 0) { + STD_TP_sbrk=k; + if (Debug) + printf("Using env USC_TP_SBRK, Set STD_TP_sbrk to %d\n", + STD_TP_sbrk); + } + } + +#if !defined(UCLINUX) + if ((ptr = getenv("USC_LP_SBRK")) != NULL) { + if (sscanf(ptr, "%i", &k) == 1 && k >= 0) { + STD_LP_sbrk=k; + if (Debug) + printf("Using env USC_LP_SBRK, Set STD_LP_sbrk to %d\n", + STD_LP_sbrk); + } + } +#endif /* if !defined(UCLINUX) */ + + if ((ptr = getenv("USC_LP_RECFUN")) != NULL) { + if (sscanf(ptr, "%i", &k) == 1 && k >= 0) { + STD_LP_recfun = k; + if (STD_bigstack != NULL) + STD_bigstack = malloc(sizeof(struct usc_bigstack_t)); + if (Debug) + printf("Using env USC_LP_RECFUN, Set STD_LP_recfun to %d\n", + STD_LP_recfun); + } + } + + if ((ptr = getenv("USC_LD_RECFUN")) != NULL) { + if (sscanf(ptr, "%i", &k) == 1 && k >= 0) { + STD_LD_recfun = k; + if (STD_bigstack != NULL) + STD_bigstack = malloc(sizeof(struct usc_bigstack_t)); + if (Debug) + printf("Using env USC_LD_RECFUN, Set STD_LD_recfun to %d\n", + STD_LD_recfun); + } + } + +#if UNIT_TEST + printf("The following variables after option and env parsing:\n"); + printf("STD_FUNCTIONAL_TEST = %d\n", STD_FUNCTIONAL_TEST); + printf("STD_LOOP_DURATION = %f\n", STD_LOOP_DURATION); + printf("STD_LOOP_DELAY = %f\n", STD_LOOP_DELAY); + printf("STD_COPIES = %d\n", STD_COPIES); + printf("STD_LOOP_COUNT = %d\n", STD_LOOP_COUNT); + printf("STD_INFINITE = %d\n", STD_INFINITE); + printf("STD_TIMING_ON = %d\n", STD_TIMING_ON); + printf("STD_ERRNO_LOG = %d\n", STD_ERRNO_LOG); + printf("STD_PAUSE = %d\n", STD_PAUSE); +#endif + + return((char *) NULL); + +} /* end of parse_opts */ + +/********************************************************************* + * print_help() - print help message and user help message + *********************************************************************/ +void print_help(void (*user_help)()) +{ + STD_opts_help(); + + if (user_help) + user_help(); +} + +/********************************************************************* + * STD_opts_help() - return a help string for the STD_OPTIONS. + *********************************************************************/ +void STD_opts_help() +{ + int i; + + for (i = 0; std_options[i].optstr; ++i) { + if (std_options[i].help) + printf("%s", std_options[i].help); + } +} + +/* + * routine to goto when we get the SIGUSR1 for STD_PAUSE + */ +void STD_go(int sig) +{ + return; +} + +/*********************************************************************** + * This function will do desired end of global setup test + * hooks. + * Currently it will only do a pause waiting for sigusr1 if + * STD_PAUSE is set. + * + ***********************************************************************/ +int usc_global_setup_hook() +{ +#ifndef UCLINUX + int cnt; + /* temp variable to store old signal action to be restored after pause */ + int (*_TMP_FUNC)(void); + + /* + * Fork STD_COPIES-1 copies. + */ + for (cnt=1;cnt +#include "pattern.h" + +/* + * The routines in this module are used to fill/check a data buffer + * with/against a known pattern. + */ + +int +pattern_check(buf, buflen, pat, patlen, patshift) +char *buf; +int buflen; +char *pat; +int patlen; +int patshift; +{ + int nb, ncmp, nleft; + char *cp; + + if (patlen) + patshift = patshift % patlen; + + cp = buf; + nleft = buflen; + + /* + * The following 2 blocks of code are to compare the first patlen + * bytes of buf. We need 2 checks if patshift is > 0 since we + * must check the last (patlen - patshift) bytes, and then the + * first (patshift) bytes. + */ + + nb = patlen - patshift; + if (nleft < nb) { + return (memcmp(cp, pat + patshift, nleft) ? -1 : 0); + } else { + if (memcmp(cp, pat + patshift, nb)) + return -1; + + nleft -= nb; + cp += nb; + } + + if (patshift > 0) { + nb = patshift; + if (nleft < nb) { + return (memcmp(cp, pat, nleft) ? -1 : 0); + } else { + if (memcmp(cp, pat, nb)) + return -1; + + nleft -= nb; + cp += nb; + } + } + + /* + * Now, verify the rest of the buffer using the algorithm described + * in the function header. + */ + + ncmp = cp - buf; + while (ncmp < buflen) { + nb = (ncmp < nleft) ? ncmp : nleft; + if (memcmp(buf, cp, nb)) + return -1; + + cp += nb; + ncmp += nb; + nleft -= nb; + } + + return 0; +} + +int +pattern_fill(buf, buflen, pat, patlen, patshift) +char *buf; +int buflen; +char *pat; +int patlen; +int patshift; +{ + int trans, ncopied, nleft; + char *cp; + + if (patlen) + patshift = patshift % patlen; + + cp = buf; + nleft = buflen; + + /* + * The following 2 blocks of code are to fill the first patlen + * bytes of buf. We need 2 sections if patshift is > 0 since we + * must first copy the last (patlen - patshift) bytes into buf[0]..., + * and then the first (patshift) bytes of pattern following them. + */ + + trans = patlen - patshift; + if (nleft < trans) { + memcpy(cp, pat + patshift, nleft); + return 0; + } else { + memcpy(cp, pat + patshift, trans); + nleft -= trans; + cp += trans; + } + + if (patshift > 0) { + trans = patshift; + if (nleft < trans) { + memcpy(cp, pat, nleft); + return 0; + } else { + memcpy(cp, pat, trans); + nleft -= trans; + cp += trans; + } + } + + /* + * Now, fill the rest of the buffer using the algorithm described + * in the function header comment. + */ + + ncopied = cp - buf; + while (ncopied < buflen) { + trans = (ncopied < nleft) ? ncopied : nleft; + memcpy(cp, buf, trans); + cp += trans; + ncopied += trans; + nleft -= trans; + } + + return(0); +} \ No newline at end of file diff --git a/ltp_framework/lib/random_range.c b/ltp_framework/lib/random_range.c new file mode 100644 index 0000000..b1bde84 --- /dev/null +++ b/ltp_framework/lib/random_range.c @@ -0,0 +1,917 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +#include +#include +#include +#include +#include "random_range.h" + +/* + * Internal format of the range array set up by parse_range() + */ + +struct range { + int min; + int max; + int mult; +}; + +/* + * parse_ranges() is a function to parse a comma-separated list of range + * tokens each having the following form: + * + * num + * or + * min:max[:mult] + * + * any of the values may be blank (ie. min::mult, :max, etc.) and default + * values for missing arguments may be supplied by the caller. + * + * The special first form is short hand for 'num:num'. + * + * After parsing the string, the ranges are put into an array of integers, + * which is malloc'd by the routine. The min, max, and mult entries of each + * range can be extracted from the array using the range_min(), range_max(), + * and range_mult() functions. + * + * It is the responsibility of the caller to free the space allocated by + * parse_ranges() - a single call to free() will free the space. + * + * str The string to parse - assumed to be a comma-separated + * list of tokens having the above format. + * defmin default value to plug in for min, if it is missing + * defmax default value to plug in for max, if it is missing + * defmult default value to plug in for mult, if missing + * parse_func A user-supplied function pointer, which parse_ranges() + * can call to parse the min, max, and mult strings. This + * allows for customized number formats. The function + * MUST have the following prototype: + * parse_func(char *str, int *val) + * The function should return -1 if str cannot be parsed + * into an integer, or >= 0 if it was successfully + * parsed. The resulting integer will be stored in + * *val. If parse_func is NULL, parse_ranges will parse + * the tokens in a manner consistent with the the sscanf + * %i format. + * range_ptr A user-supplied char **, which will be set to point + * at malloc'd space which holds the parsed range + * values. If range_ptr is NULL, parse_ranges() just + * parses the string. The data returned in range_ptr + * should not be processed directly - use the functions + * range_min(), range_max(), and range_mult() to access + * data for a given range. + * errptr user-supplied char ** which can be set to point to a + * static error string. If errptr is NULL, it is ignored. + * + * parse_range() returns -1 on error, or the number of ranges parsed. + */ + +static int str_to_int(); +static long long divider(long long, long long, long long, long long); + +int +parse_ranges(str, defmin, defmax, defmult, parse_func, rangeptr, errptr) +char *str; +int defmin; +int defmax; +int defmult; +int (*parse_func)(); +char **rangeptr; +char **errptr; +{ + int ncommas; + char *tmpstr, *cp, *tok, *n1str, *n2str, *multstr; + struct range *rp, *ranges; + static char errmsg[256]; + + if (errptr != NULL) { + *errptr = errmsg; + } + + for (ncommas = 0, cp = str; *cp != '\0'; cp++) { + if (*cp == ',') { + ncommas++; + } + } + + if (parse_func == NULL) { + parse_func = str_to_int; + } + + tmpstr = strdup(str); + ranges = (struct range *)malloc((ncommas+1) * sizeof(struct range)); + rp = ranges; + + tok = strtok(tmpstr, ","); + while (tok != NULL) { + n1str = tok; + n2str = NULL; + multstr = NULL; + + rp->min = defmin; + rp->max = defmax; + rp->mult = defmult; + + if ((cp = strchr(n1str, ':')) != NULL) { + *cp = '\0'; + n2str = cp+1; + + if ((cp = strchr(n2str, ':')) != NULL) { + *cp = '\0'; + multstr = cp+1; + } + } + + /* + * Parse the 'min' field - if it is zero length (:n2[:mult] + * format), retain the default value, otherwise, pass the + * string to the parse function. + */ + + if ((int)strlen(n1str) > 0) { + if ((*parse_func)(n1str, &rp->min) < 0) { + sprintf(errmsg, "error parsing string %s into an integer", n1str); + free(tmpstr); + free(ranges); + return -1; + } + } + + /* + * Process the 'max' field - if one was not present (n1 format) + * set max equal to min. If the field was present, but + * zero length (n1: format), retain the default. Otherwise + * pass the string to the parse function. + */ + + if (n2str == NULL) { + rp->max = rp->min; + } else if ((int)strlen(n2str) > 0) { + if ((*parse_func)(n2str, &rp->max) < 0) { + sprintf(errmsg, "error parsing string %s into an integer", n2str); + free(tmpstr); + free(ranges); + return -1; + } + } + + /* + * Process the 'mult' field - if one was not present + * (n1:n2 format), or the field was zero length (n1:n2: format) + * then set the mult field to defmult - otherwise pass then + * mult field to the parse function. + */ + + if (multstr != NULL && (int)strlen(multstr) > 0) { + if ((*parse_func)(multstr, &rp->mult) < 0) { + sprintf(errmsg, "error parsing string %s into an integer", multstr); + free(tmpstr); + free(ranges); + return -1; + } + } + + rp++; + tok = strtok(NULL, ","); + } + + free(tmpstr); + + if (rangeptr != NULL) { + *rangeptr = (char *)ranges; + } else { + free(ranges); /* just running in parse mode */ + } + + return (rp - ranges); +} + +/* + * The default integer-parsing function + */ + +static int +str_to_int(str, ip) +char *str; +int *ip; +{ + char c; + + if (sscanf(str, "%i%c", ip, &c) != 1) { + return -1; + } else { + return 0; + } +} + +/* + * Three simple functions to return the min, max, and mult values for a given + * range. It is assumed that rbuf is a range buffer set up by parse_ranges(), + * and that r is a valid range within that buffer. + */ + +int +range_min(rbuf, r) +char *rbuf; +int r; +{ + return ((struct range *)rbuf)[r].min; +} + +int +range_max(rbuf, r) +char *rbuf; +int r; +{ + return ((struct range *)rbuf)[r].max; +} + +int +range_mult(rbuf, r) +char *rbuf; +int r; +{ + return ((struct range *)rbuf)[r].mult; +} + +/***************************************************************************** + * random_range(int start, int end, int mult, char **errp) + * + * Returns a psuedo-random number which is >= 'start', <= 'end', and a multiple + * of 'mult'. Start and end may be any valid integer, but mult must be an + * integer > 0. errp is a char ** which will be set to point to a static + * error message buffer if it is not NULL, and an error occurs. + * + * The errp is the only way to check if the routine fails - currently the only + * failure conditions are: + * + * mult < 1 + * no numbers in the start-end range that are a multiple of 'mult' + * + * If random_range_fails, and errp is a valid pointer, it will point to an + * internal error buffer. If errp is a vaild pointer, and random_range + * is successful, errp will be set to NULL. + * + * Note - if mult is 1 (the most common case), there are error conditions + * possible, and errp need not be used. + * + * Note: Uses lrand48(), assuming that set_random_seed() uses srand48() when + * setting the seed. + *****************************************************************************/ + +long +random_range(min, max, mult, errp) +int min; +int max; +int mult; +char **errp; +{ + int r, nmults, orig_min, orig_max, orig_mult, tmp; + extern long lrand48(); + static char errbuf[128]; + + /* + * Sanity check + */ + + if (mult < 1) { + if (errp != NULL) { + sprintf(errbuf, "mult arg must be greater than 0"); + *errp = errbuf; + } + return -1; + } + + /* + * Save original parameter values for use in error message + */ + + orig_min = min; + orig_max = max; + orig_mult = mult; + + /* + * switch min/max if max < min + */ + + if (max < min) { + tmp = max; + max = min; + min = tmp; + } + + /* + * select the random number + */ + + if ((r = min % mult)) /* bump to the next higher 'mult' multiple */ + min += mult - r; + + if ((r = max % mult)) /* reduce to the next lower 'mult' multiple */ + max -= r; + + if (min > max) { /* no 'mult' multiples between min & max */ + if (errp != NULL) { + sprintf(errbuf, "no numbers in the range %d:%d that are a multiple of %d", orig_min, orig_max, orig_mult); + *errp = errbuf; + } + return -1; + } + + if (errp != NULL) { + *errp = NULL; + } + + nmults = ((max - min) / mult) + 1; +#if CRAY + /* + * If max is less than 2gb, then the value can fit in 32 bits + * and the standard lrand48() routine can be used. + */ + if (max <= (long)2147483647) { + return (long) (min + (((long)lrand48() % nmults) * mult)); + } else { + /* + * max is greater than 2gb - meeds more than 32 bits. + * Since lrand48 only will get a number up to 32bits. + */ + long randnum; + randnum=divider(min, max, 0, -1); + return (long) (min + ((randnum % nmults) * mult)); + } + +#else + return (min + ((lrand48() % nmults) * mult)); +#endif + +} + +/* + * Just like random_range, but all values are longs. + */ +long +random_rangel(min, max, mult, errp) +long min; +long max; +long mult; +char **errp; +{ + long r, nmults, orig_min, orig_max, orig_mult, tmp; + extern long lrand48(); + static char errbuf[128]; + + /* + * Sanity check + */ + + if (mult < 1) { + if (errp != NULL) { + sprintf(errbuf, "mult arg must be greater than 0"); + *errp = errbuf; + } + return -1; + } + + /* + * Save original parameter values for use in error message + */ + + orig_min = min; + orig_max = max; + orig_mult = mult; + + /* + * switch min/max if max < min + */ + + if (max < min) { + tmp = max; + max = min; + min = tmp; + } + + /* + * select the random number + */ + + if ((r = min % mult)) /* bump to the next higher 'mult' multiple */ + min += mult - r; + + if ((r = max % mult)) /* reduce to the next lower 'mult' multiple */ + max -= r; + + if (min > max) { /* no 'mult' multiples between min & max */ + if (errp != NULL) { + sprintf(errbuf, + "no numbers in the range %ld:%ld that are a multiple of %ld", + orig_min, orig_max, orig_mult); + *errp = errbuf; + } + return -1; + } + + if (errp != NULL) { + *errp = NULL; + } + + nmults = ((max - min) / mult) + 1; +#if CRAY || (_MIPS_SZLONG == 64) + /* + * If max is less than 2gb, then the value can fit in 32 bits + * and the standard lrand48() routine can be used. + */ + if (max <= (long)2147483647) { + return (long) (min + (((long)lrand48() % nmults) * mult)); + } else { + /* + * max is greater than 2gb - meeds more than 32 bits. + * Since lrand48 only will get a number up to 32bits. + */ + long randnum; + randnum=divider(min, max, 0, -1); + return (long) (min + ((randnum % nmults) * mult)); + } + +#else + return (min + ((lrand48() % nmults) * mult)); +#endif +} + +/* + * Attempts to be just like random_range, but everything is long long (64 bit) + */ +long long +random_rangell(min, max, mult, errp) +long long min; +long long max; +long long mult; +char **errp; +{ + long long r, nmults, orig_min, orig_max, orig_mult, tmp; + long long randnum; + extern long lrand48(); + static char errbuf[128]; + + /* + * Sanity check + */ + + if (mult < 1) { + if (errp != NULL) { + sprintf(errbuf, "mult arg must be greater than 0"); + *errp = errbuf; + } + return -1; + } + + /* + * Save original parameter values for use in error message + */ + + orig_min = min; + orig_max = max; + orig_mult = mult; + + /* + * switch min/max if max < min + */ + + if (max < min) { + tmp = max; + max = min; + min = tmp; + } + + /* + * select the random number + */ + + if ((r = min % mult)) /* bump to the next higher 'mult' multiple */ + min += mult - r; + + if ((r = max % mult)) /* reduce to the next lower 'mult' multiple */ + max -= r; + + if (min > max) { /* no 'mult' multiples between min & max */ + if (errp != NULL) { + sprintf(errbuf, + "no numbers in the range %lld:%lld that are a multiple of %lld", + orig_min, orig_max, orig_mult); + *errp = errbuf; + } + return -1; + } + + if (errp != NULL) { + *errp = NULL; + } + + nmults = ((max - min) / mult) + 1; + /* + * If max is less than 2gb, then the value can fit in 32 bits + * and the standard lrand48() routine can be used. + */ + if (max <= (long)2147483647) { + return (long long) (min + (((long long)lrand48() % nmults) * mult)); + } else { + /* + * max is greater than 2gb - meeds more than 32 bits. + * Since lrand48 only will get a number up to 32bits. + */ + randnum=divider(min, max, 0, -1); + return (long long) (min + ((randnum % nmults) * mult)); + } + +} + +/* + * This functional will recusively call itself to return a random + * number min and max. It was designed to work the 64bit numbers + * even when compiled as 32 bit process. + * algorithm: to use the official lrand48() routine - limited to 32 bits. + * find the difference between min and max (max-min). + * if the difference is 2g or less, use the random number gotton from lrand48(). + * Determine the midway point between min and max. + * if the midway point is less than 2g from min or max, + * randomly add the random number gotton from lrand48() to + * either min or the midpoint. + * Otherwise, call outself with min and max being min and midway value or + * midway value and max. This will reduce the range in half. + */ +static long long +divider(long long min, long long max, long long cnt, long long rand) +{ + long long med, half, diff; + + /* + * prevent run away code. We are dividing by two each count. + * if we get to a count of more than 32, we should have gotten + * to 2gb. + */ + if (cnt > 32) + return -1; + + /* + * Only get a random number the first time. + */ + if (cnt == 0 || rand < -1) { + rand = (long long)lrand48(); /* 32 bit random number */ + } + + diff = max - min; + + if (diff <= 2147483647) + return min + rand; + + half = diff/(long long)2; /* half the distance between min and max */ + med = min + half; /* med way point between min and max */ + +#if DEBUG +printf("divider: min=%lld, max=%lld, cnt=%lld, rand=%lld\n", min, max, cnt, rand); +printf(" diff = %lld, half = %lld, med = %lld\n", diff, half, med); +#endif + + if (half <= 2147483647) { + /* + * If half is smaller than 2gb, we can use the random number + * to pick the number within the min to med or med to max + * if the cnt bit of rand is zero or one, respectively. + */ + if (rand & (1<> 1; + nshift++; + } + + return 01L << (nshift-1); + +} + + +#if RANDOM_BIT_UNITTEST +/* + * The following is a unit test main function for random_bit(). + */ +main(argc, argv) +int argc; +char **argv; +{ + int ind; + int cnt, iter; + long mask, ret; + + printf("test for first and last bit set\n"); + mask=1L; + ret=random_bit(mask); + printf("random_bit(%#o) returned %#o\n", mask, ret); + + mask=1L<<(sizeof(long)*8-1); + ret=random_bit(mask); + printf("random_bit(%#o) returned %#o\n", mask, ret); + + if (argc >= 3) { + iter=atoi(argv[1]); + for (ind=2; ind= 3) { + if (sscanf(argv[2], "%i", &iter) != 1) { + printf("Usage: %s [func iterations] \n", argv[0]); + printf("argv[2] is not a number\n"); + exit(1); + } + } + + + /* + * random_rangel () + */ + if (strcmp(argv[1], "random_rangel") == 0) { + ltmin=lmax; + part = lmax/PARTNUM; + for (ind=0; ind ltmax) + ltmax = lret; + for (ind=0; ind valbound[PARTNUM-1]) { + cntarr[PARTNUM-1]++; + } + } + for (ind=0; ind lltmax) + lltmax = llret; + + for (ind=0; ind lvalbound[PARTNUM-1]) { + cntarr[PARTNUM-1]++; + } + } + for (ind=0; ind itmax) + itmax = lret; + + for (ind=0; ind valbound[PARTNUM-1]) { + cntarr[PARTNUM-1]++; + } + } + for (ind=0; ind= 3: + * Remove the directory with unlink() + * Else + * Remove the directory with rmdir() + * Close the directory and free the pointers + * + * RETURN VALUE + * If there are any problems, rmobj() will set errmsg (if it was not + * NULL) and return -1. Otherwise it will return 0. + * + ************************************************************/ +#include /* for errno */ +#include /* for NULL */ +#include /* for malloc() */ +#include /* for string function */ +#include /* for PATH_MAX */ +#include /* for opendir(), readdir(), closedir(), stat() */ +#include /* for [l]stat() */ +#include /* for opendir(), readdir(), closedir() */ +#include /* for rmdir(), unlink() */ +#include "rmobj.h" + +#define SYSERR strerror(errno) + +int +rmobj(char *obj, char **errmsg) +{ + int ret_val = 0; /* return value from this routine */ + DIR *dir; /* pointer to a directory */ + struct dirent *dir_ent; /* pointer to directory entries */ + char dirobj[PATH_MAX]; /* object inside directory to modify */ + struct stat statbuf; /* used to hold stat information */ + static char err_msg[1024]; /* error message */ + + /* Determine the file type */ + if (lstat(obj, &statbuf) < 0) { + if (errmsg != NULL) { + sprintf(err_msg, "lstat(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + + /* Take appropriate action, depending on the file type */ + if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { + /* object is a directory */ + + /* Do NOT perform the request if the directory is "/" */ + if (!strcmp(obj, "/")) { + if (errmsg != NULL) { + sprintf(err_msg, "Cannot remove /"); + *errmsg = err_msg; + } + return -1; + } + + /* Open the directory to get access to what is in it */ + if ((dir = opendir(obj)) == NULL) { + if (rmdir(obj) != 0) { + if (errmsg != NULL) { + sprintf(err_msg, "rmdir(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } else { + return 0; + } + } + + /* Loop through the entries in the directory, removing each one */ + for (dir_ent = (struct dirent *)readdir(dir); + dir_ent != NULL; + dir_ent = (struct dirent *)readdir(dir)) { + + /* Don't remove "." or ".." */ + if (!strcmp(dir_ent->d_name, ".") || !strcmp(dir_ent->d_name, "..")) + continue; + + /* Recursively call this routine to remove the current entry */ + sprintf(dirobj, "%s/%s", obj, dir_ent->d_name); + if (rmobj(dirobj, errmsg) != 0) + ret_val = -1; + } + + /* Close the directory */ + closedir(dir); + + /* If there were problems removing an entry, don't attempt to + remove the directory itself */ + if (ret_val == -1) + return -1; + + /* Get the link count, now that all the entries have been removed */ + if (lstat(obj, &statbuf) < 0) { + if (errmsg != NULL) { + sprintf(err_msg, "lstat(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + + /* Remove the directory itself */ + if (statbuf.st_nlink >= 3) { + /* The directory is linked; unlink() must be used */ + if (unlink(obj) < 0) { + if (errmsg != NULL) { + sprintf(err_msg, "unlink(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + } else { + /* The directory is not linked; remove() can be used */ + if (remove(obj) < 0) { + if (errmsg != NULL) { + sprintf(err_msg, "remove(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + } + } else { + /* object is not a directory; just use unlink() */ + if (unlink(obj) < 0) { + if (errmsg != NULL) { + sprintf(err_msg, "unlink(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + } /* if obj is a directory */ + + /* + * Everything must have went ok. + */ + return 0; +} /* rmobj() */ \ No newline at end of file diff --git a/ltp_framework/lib/safe_macros.c b/ltp_framework/lib/safe_macros.c new file mode 100644 index 0000000..11f5fe6 --- /dev/null +++ b/ltp_framework/lib/safe_macros.c @@ -0,0 +1,312 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test.h" +#include "safe_macros.h" + +char * +safe_basename(const char *file, const int lineno, void (*cleanup_fn)(void), + char *path) +{ + char *rval; + + rval = basename(path); + if (rval == NULL) + tst_brkm(TBROK|TERRNO, cleanup_fn, "basename failed at %s:%d", + file, lineno); + + return (rval); +} + +int +safe_chdir(const char *file, const int lineno, void (*cleanup_fn)(void), + const char *path) +{ + int rval; + + rval = chdir(path); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "chdir failed at %s:%d", + file, lineno); + + return (rval); +} + +int +safe_close(const char *file, const int lineno, void (*cleanup_fn)(void), + int fildes) +{ + int rval; + + rval = close(fildes); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "close failed at %s:%d", + file, lineno); + + return (rval); +} + +int +safe_creat(const char *file, const int lineno, void (*cleanup_fn)(void), + char *pathname, mode_t mode) +{ + int rval; + + rval = creat(pathname, mode); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "pipe failed at %s:%d", + file, lineno); + + return (rval); +} + +char * +safe_dirname(const char *file, const int lineno, void (*cleanup_fn)(void), + char *path) +{ + char *rval; + + rval = dirname(path); + if (rval == NULL) + tst_brkm(TBROK|TERRNO, cleanup_fn, "dirname failed at %s:%d", + file, lineno); + + return (rval); +} + +char * +safe_getcwd(const char *file, const int lineno, void (*cleanup_fn)(void), + char *buf, size_t size) +{ + char *rval; + + rval = getcwd(buf, size); + if (rval == NULL) + tst_brkm(TBROK|TERRNO, cleanup_fn, "getcwd failed at %s:%d", + file, lineno); + + return (rval); +} + +struct passwd* +safe_getpwnam(const char *file, const int lineno, void (*cleanup_fn)(void), + const char *name) +{ + struct passwd *rval; + + rval = getpwnam(name); + if (rval == NULL) + tst_brkm(TBROK|TERRNO, cleanup_fn, "getpwnam failed at %s:%d", + file, lineno); + + return (rval); +} + +int +safe_getrusage(const char *file, const int lineno, void (*cleanup_fn)(void), + int who, struct rusage *usage) +{ + int rval; + + rval = getrusage(who, usage); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "getrusage failed at %s:%d", + file, lineno); + + return rval; +} + +void* +safe_malloc(const char *file, const int lineno, void (*cleanup_fn)(void), + size_t size) +{ + void *rval; + + rval = malloc(size); + if (rval == NULL) + tst_brkm(TBROK|TERRNO, cleanup_fn, "malloc failed at %s:%d", + file, lineno); + + return (rval); +} + +int +safe_mkdir(const char *file, const int lineno, void (*cleanup_fn)(void), + const char *pathname, mode_t mode) +{ + int rval; + + rval = mkdir(pathname, mode); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "mkdir failed at %s:%d", + file, lineno); + + return (rval); +} + +void* +safe_mmap(const char *file, const int lineno, void (*cleanup_fn)(void), + void *addr, size_t length, int prot, int flags, int fd, off_t offset) +{ + void *rval; + + rval = mmap(addr, length, prot, flags, fd, offset); + if (rval == MAP_FAILED) + tst_brkm(TBROK|TERRNO, cleanup_fn, "mmap failed at %s:%d", + file, lineno); + + return (rval); +} + +int +safe_munmap(const char *file, const int lineno, void (*cleanup_fn)(void), + void *addr, size_t length) +{ + int rval; + + rval = munmap(addr, length); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "munmap failed at %s:%d", + file, lineno); + + return (rval); +} + +int +safe_open(const char *file, const int lineno, void (*cleanup_fn)(void), + const char *pathname, int oflags, ...) +{ + va_list ap; + int rval; + mode_t mode; + + va_start(ap, oflags); + mode = va_arg(ap, mode_t); + va_end(ap); + + rval = open(pathname, oflags, mode); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "open failed at %s:%d", + file, lineno); + + return (rval); +} + +int +safe_pipe(const char *file, const int lineno, void (*cleanup_fn)(void), + int fildes[2]) +{ + int rval; + + rval = pipe(fildes); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "pipe failed at %s:%d", + file, lineno); + + return (rval); +} + +ssize_t +safe_read(const char *file, const int lineno, void (*cleanup_fn)(void), + char len_strict, int fildes, void *buf, size_t nbyte) +{ + ssize_t rval; + + rval = read(fildes, buf, nbyte); + if ((len_strict == 0 && rval == -1) || rval != nbyte) + tst_brkm(TBROK|TERRNO, cleanup_fn, "read failed at %s:%d", + file, lineno); + + return (rval); +} + + int +safe_setegid(const char *file, const int lineno, void (*cleanup_fn)(void), + gid_t egid) +{ + int rval; + + rval = setegid(egid); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "setegid failed at %s:%d", + file, lineno); + + return (rval); +} + +int +safe_seteuid(const char *file, const int lineno, void (*cleanup_fn)(void), + uid_t euid) +{ + int rval; + + rval = seteuid(euid); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "seteuid failed at %s:%d", + file, lineno); + + return (rval); +} + +int +safe_setgid(const char *file, const int lineno, void (*cleanup_fn)(void), + gid_t gid) +{ + int rval; + + rval = setgid(gid); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "setgid failed at %s:%d", + file, lineno); + + return (rval); +} + +int +safe_setuid(const char *file, const int lineno, void (*cleanup_fn)(void), + uid_t uid) +{ + int rval; + + rval = setuid(uid); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "setuid failed at %s:%d", + file, lineno); + + return (rval); +} + +int +safe_unlink(const char *file, const int lineno, void (*cleanup_fn)(void), + const char *pathname) +{ + int rval; + + rval = unlink(pathname); + if (rval == -1) + tst_brkm(TBROK|TERRNO, cleanup_fn, "unlink failed at %s:%d", + file, lineno); + + return (rval); +} + +ssize_t +safe_write(const char *file, const int lineno, void (cleanup_fn)(void), + char len_strict, int fildes, const void *buf, size_t nbyte) +{ + ssize_t rval; + + rval = write(fildes, buf, nbyte); + if ((len_strict == 0 && rval == -1) || rval != nbyte) + tst_brkm(TBROK|TERRNO, cleanup_fn, "write failed at %s:%d", + file, lineno); + + return (rval); +} diff --git a/ltp_framework/lib/search_path.c b/ltp_framework/lib/search_path.c new file mode 100644 index 0000000..a9dff82 --- /dev/null +++ b/ltp_framework/lib/search_path.c @@ -0,0 +1,277 @@ +/* $Header: /cvsroot/ltp/ltp/lib/search_path.c,v 1.4 2009/07/20 10:59:32 vapier Exp $ */ + +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ + + +/********************************************************** + * + * UNICOS Feature Test and Evaluation - Cray Research, Inc. + * + * FUNCTION NAME : search_path + * + * FUNCTION TITLE : search PATH locations for desired filename + * + * SYNOPSIS: + * int search_path(cmd, res_path, access_mode, fullpath) + * char *cmd; + * char *res_path; + * int access_mode; + * int fullpath; + * + * AUTHOR : Richard Logan + * + * INITIAL RELEASE : UNICOS 7.0 + * + * DESCRIPTION + * Search_path will walk through PATH and attempt to find "cmd". If cmd is + * a full or relative path, it is checked but PATH locations are not scanned. + * search_path will put the resulting path in res_path. It is assumed + * that res_path points to a string that is at least PATH_MAX + * (or MAXPATHLEN on the suns) in size. Access_mode is just as is + * says, the mode to be used on access to determine if cmd can be found. + * If fullpath is set, res_path will contain the full path to cmd. + * If it is not set, res_path may or may not contain the full path to cmd. + * If fullpath is not set, the path in PATH prepended to cmd is used, + * which could be a relative path. If fullpath is set, the current + * directory is prepended to path/cmd before access is called. + * If cmd is found, search_path will return 0. If cmd cannot be + * found, 1 is returned. If an error has occurred, -1 is returned + * and an error mesg is placed in res_path. + * If the length of path/cmd is larger then PATH_MAX, then that path + * location is skipped. + * + *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ + +#include +#include +#include +#include +#include +#include +#include + + +struct stat stbuf; + +#ifndef AS_CMD +#define AS_CMD 0 +#endif + +/* + * Make sure PATH_MAX is defined. Define it to MAXPATHLEN, if set. Otherwise + * set it to 1024. + */ +#ifndef PATH_MAX +#ifndef MAXPATHLEN +#define PATH_MAX 1024 +#else /* MAXPATHLEN */ +#define PATH_MAX MAXPATHLEN +#endif /* MAXPATHLEN */ +#endif /* PATH_MAX */ + + +#if AS_CMD +main(argc, argv) +int argc; +char **argv; +{ + char path[PATH_MAX]; + int ind; + + if (argc <= 1) { + printf("missing argument\n"); + exit(1); + } + + for (ind=1;ind < argc; ind++) { + if (search_path(argv[ind], path, F_OK, 0) < 0) { + printf("ERROR: %s\n", path); + } + else { + printf("path of %s is %s\n", argv[ind], path); + } + } + +} + +#endif + +/* + */ +int +search_path(cmd, res_path, access_mode, fullpath) +char *cmd; /* The requested filename */ +char *res_path; /* The resulting path or error mesg */ +int access_mode; /* the mode used by access(2) */ +int fullpath; /* if set, cwd will be prepended to all non-full paths */ +{ + char *cp; /* used to scan PATH for directories */ + int ret; /* return value from access */ + char *pathenv; + char tmppath[PATH_MAX]; + char curpath[PATH_MAX]; + char *path; + int lastpath; + int toolong=0; + +#if DEBUG +printf("search_path: cmd = %s, access_mode = %d, fullpath = %d\n", cmd, access_mode, fullpath); +#endif + + /* + * full or relative path was given + */ + if ((cmd[0] == '/') || ( (cp=strchr(cmd, '/')) != NULL )) { + if (access(cmd, access_mode) == 0) { + + if (cmd[0] != '/') { /* relative path */ + if (getcwd(curpath, PATH_MAX) == NULL) { + strcpy(res_path, curpath); + return -1; + } + if ((strlen(curpath) + strlen(cmd) + 1) > (size_t)PATH_MAX) { + sprintf(res_path, "cmd (as relative path) and cwd is longer than %d", + PATH_MAX); + return -1; + } + sprintf(res_path, "%s/%s", curpath, cmd); + } + else + strcpy(res_path, cmd); + return 0; + } + else { + sprintf(res_path, "file %s not found", cmd); + return -1; + } + } + + /* get the PATH variable */ + if ((pathenv=getenv("PATH")) == NULL) { + /* no path to scan, return */ + sprintf(res_path, "Unable to get PATH env. variable"); + return -1; + } + + /* + * walk through each path in PATH. + * Each path in PATH is placed in tmppath. + * pathenv cannot be modified since it will affect PATH. + * If a signal came in while we have modified the PATH + * memory, we could create a problem for the caller. + */ + + curpath[0]='\0'; + + cp = pathenv; + path = pathenv; + lastpath = 0; + for (;;) { + + if (lastpath) + break; + + if (cp != pathenv) + path = ++cp; /* already set on first iteration */ + + /* find end of current path */ + + for (; ((*cp != ':') && (*cp != '\0')); cp++); + + /* + * copy path to tmppath so it can be NULL terminated + * and so we do not modify path memory. + */ + strncpy(tmppath, path, (cp-path) ); + tmppath[cp-path]='\0'; +#if DEBUG +printf("search_path: tmppath = %s\n", tmppath); +#endif + + if (*cp == '\0') + lastpath=1; /* this is the last path entry */ + + /* Check lengths so not to overflow res_path */ + if (strlen(tmppath) + strlen(cmd) + 2 > (size_t)PATH_MAX) { + toolong++; + continue; + } + + sprintf(res_path, "%s/%s", tmppath, cmd); +#if DEBUG +printf("search_path: res_path = '%s'\n", res_path); +#endif + + + /* if the path is not full at this point, prepend the current + * path to get the full path. + * Note: this could not be wise to do when under a protected + * directory. + */ + + if (fullpath && res_path[0] != '/') { /* not a full path */ + if (curpath[0] == '\0') { + if (getcwd(curpath, PATH_MAX) == NULL) { + strcpy(res_path, curpath); + return -1; + } + } + if ((strlen(curpath) + strlen(res_path) + 2) > (size_t)PATH_MAX) { + toolong++; + continue; + } + sprintf(tmppath, "%s/%s", curpath, res_path); + strcpy(res_path, tmppath); +#if DEBUG +printf("search_path: full res_path= '%s'\n", res_path); +#endif + + } + + + if ((ret=access(res_path, access_mode)) == 0) { +#if DEBUG +printf("search_path: found res_path = %s\n", res_path); +#endif + return 0; + } + } + + /* return failure */ + if (toolong) + sprintf(res_path, + "Unable to find file, %d path/file strings were too long", toolong); + else + strcpy(res_path, "Unable to find file"); + return 1; /* not found */ +} diff --git a/ltp_framework/lib/self_exec.c b/ltp_framework/lib/self_exec.c new file mode 100644 index 0000000..a457468 --- /dev/null +++ b/ltp_framework/lib/self_exec.c @@ -0,0 +1,218 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: t -*- */ +/* + * self_exec.c: self_exec magic required to run child functions on uClinux + * + * Copyright (C) 2005 Paul J.Y. Lahaie + * + * 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. + * + * This software was produced by Steamballoon Incorporated + * 55 Byward Market Square, 2nd Floor North, Ottawa, ON K1N 9C3, Canada + */ + +#define _GNU_SOURCE /* for asprintf */ + +#include "config.h" + +#ifdef UCLINUX + +#include +#include +#include +#include "test.h" + +/* Set from parse_opts.c: */ +char *child_args; /* Arguments to child when -C is used */ + +static char *start_cwd; /* Stores the starting directory for self_exec */ + +int asprintf(char **app, const char *fmt, ...) +{ + va_list ptr; + int rv; + char *p; + + /* + * First iteration - find out size of buffer required and allocate it. + */ + va_start(ptr, fmt); + rv = vsnprintf(NULL, 0, fmt, ptr); + va_end(ptr); + + p = malloc(++rv); /* allocate the buffer */ + *app = p; + if (!p) { + return -1; + } + + /* + * Second iteration - actually produce output. + */ + va_start(ptr, fmt); + rv = vsnprintf(p, rv, fmt, ptr); + va_end(ptr); + + return rv; +} + +void +maybe_run_child(void (*child)(), char *fmt, ...) +{ + va_list ap; + char *child_dir; + char *p, *tok; + int *iptr, i, j; + char *s; + char **sptr; + char *endptr; + + /* Store the current directory for later use. */ + start_cwd = getcwd(NULL, 0); + + if (child_args) { + char *args = strdup(child_args); + + child_dir = strtok(args, ","); + if (strlen(child_dir) == 0) { + tst_resm(TBROK, NULL, "Could not get directory from -C option"); + tst_exit(); + } + + va_start(ap, fmt); + + for (p = fmt; *p; p++) { + tok = strtok(NULL, ","); + if (!tok || strlen(tok) == 0) { + tst_resm(TBROK, "Invalid argument to -C option"); + tst_exit(); + } + + switch (*p) { + case 'd': + iptr = va_arg(ap, int *); + i = strtol(tok, &endptr, 10); + if (*endptr != '\0') { + tst_resm(TBROK, "Invalid argument to -C option"); + tst_exit(); + } + *iptr = i; + break; + case 'n': + j = va_arg(ap, int); + i = strtol(tok, &endptr, 10); + if (*endptr != '\0') { + tst_resm(TBROK, "Invalid argument to -C option"); + tst_exit(); + } + if (j != i) { + va_end(ap); + return; + } + break; + case 's': + s = va_arg(ap, char *); + if (!strncpy(s, tok, strlen(tok)+1)) { + tst_resm(TBROK, "Could not strncpy for -C option"); + tst_exit(); + } + break; + case 'S': + sptr = va_arg(ap, char **); + *sptr = strdup(tok); + if (!*sptr) { + tst_resm(TBROK, "Could not strdup for -C option"); + tst_exit(); + } + break; + default: + tst_resm(TBROK, "Format string option %c not implemented", *p); + tst_exit(); + break; + } + } + + va_end(ap); + + if (chdir(child_dir) < 0) { + tst_resm(TBROK, "Could not change to %s for child", child_dir); + tst_exit(); + } + + (*child)(); + tst_resm(TWARN, "Child function returned unexpectedly"); + /* Exit here? or exit silently? */ + } +} + +int +self_exec(char *argv0, char *fmt, ...) +{ + va_list ap; + char *p; + char *tmp_cwd; + char *arg; + int ival; + char *str; + + if ((tmp_cwd = getcwd(NULL, 0)) == NULL) { + tst_resm(TBROK, "Could not getcwd()"); + return -1; + } + + arg = strdup( tmp_cwd ); + + if (( arg = strdup( tmp_cwd )) == NULL) { + tst_resm(TBROK, "Could not produce self_exec string"); + return -1; + } + + va_start(ap, fmt); + + for (p = fmt; *p; p++) { + switch (*p) { + case 'd': + case 'n': + ival = va_arg(ap, int); + if (asprintf(&arg, "%s,%d", arg, ival) < 0) { + tst_resm(TBROK, "Could not produce self_exec string"); + return -1; + } + break; + case 's': + case 'S': + str = va_arg(ap, char *); + if (asprintf(&arg, "%s,%s", arg, str) < 0) { + tst_resm(TBROK, "Could not produce self_exec string"); + return -1; + } + break; + default: + tst_resm(TBROK, "Format string option %c not implemented", *p); + return -1; + break; + } + } + + va_end(ap); + + if (chdir(start_cwd) < 0) { + tst_resm(TBROK, "Could not change to %s for self_exec", start_cwd); + return -1; + } + + return execlp(argv0, argv0, "-C", arg, (char *) NULL); +} + +#endif /* UCLINUX */ \ No newline at end of file diff --git a/ltp_framework/lib/str_to_bytes.c b/ltp_framework/lib/str_to_bytes.c new file mode 100644 index 0000000..26e4897 --- /dev/null +++ b/ltp_framework/lib/str_to_bytes.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +#include +#include +#include "str_to_bytes.h" + +/**************************************************************************** + * str_to_bytes(s) + * + * Computes the number of bytes described by string s. s is assumed to be + * a base 10 positive (ie. >= 0) number followed by an optional single + * character multiplier. The following multipliers are supported: + * + * char mult + * ----------------- + * b BSIZE or BBSIZE + * k 1024 bytes + * K 1024 * sizeof(long) + * m 2^20 (1048576) + * M 2^20 (1048576 * sizeof(long) + * g 2^30 (1073741824) + * G 2^30 (1073741824) * sizeof(long) + * + * for instance, "1k" and "1024" would both cause str_to_bytes to return 1024. + * + * Returns -1 if mult is an invalid character, or if the integer portion of + * s is not a positive integer. + * + ****************************************************************************/ + +#if CRAY +#define B_MULT BSIZE /* block size */ +#elif sgi +#define B_MULT BBSIZE /* block size */ +#elif defined(__linux__) || defined(__sun) || defined(__hpux) +#define B_MULT DEV_BSIZE /* block size */ +#elif defined(_AIX) +#define B_MULT UBSIZE +#endif + + +#define K_MULT 1024 /* Kilo or 2^10 */ +#define M_MULT 1048576 /* Mega or 2^20 */ +#define G_MULT 1073741824 /* Giga or 2^30 */ +#define T_MULT 1099511627776 /* tera or 2^40 */ + +int +str_to_bytes(s) +char *s; +{ + char mult, junk; + int nconv; + float num; + + nconv = sscanf(s, "%f%c%c", &num, &mult, &junk); + if (nconv == 0 || nconv == 3) + return -1; + + if (nconv == 1) + return num; + + switch (mult) { + case 'b': + return (int)(num * (float)B_MULT); + case 'k': + return (int)(num * (float)K_MULT); + case 'K': + return (int)((num * (float)K_MULT) * sizeof(long)); + case 'm': + return (int)(num * (float)M_MULT); + case 'M': + return (int)((num * (float)M_MULT) * sizeof(long)); + case 'g': + return (int)(num * (float)G_MULT); + case 'G': + return (int)((num * (float)G_MULT) * sizeof(long)); + default: + return -1; + } +} + +long +str_to_lbytes(s) +char *s; +{ + char mult, junk; + long nconv; + float num; + + nconv = sscanf(s, "%f%c%c", &num, &mult, &junk); + if (nconv == 0 || nconv == 3) + return -1; + + if (nconv == 1) + return (long)num; + + switch (mult) { + case 'b': + return (long)(num * (float)B_MULT); + case 'k': + return (long)(num * (float)K_MULT); + case 'K': + return (long)((num * (float)K_MULT) * sizeof(long)); + case 'm': + return (long)(num * (float)M_MULT); + case 'M': + return (long)((num * (float)M_MULT) * sizeof(long)); + case 'g': + return (long)(num * (float)G_MULT); + case 'G': + return (long)((num * (float)G_MULT) * sizeof(long)); + default: + return -1; + } +} + +/* + * Force 64 bits number when compiled as 32 IRIX binary. + * This allows for a number bigger than 2G. + */ + +long long +str_to_llbytes(s) +char *s; +{ + char mult, junk; + long nconv; + double num; + + nconv = sscanf(s, "%lf%c%c", &num, &mult, &junk); + if (nconv == 0 || nconv == 3) + return -1; + + if (nconv == 1) + return (long long)num; + + switch (mult) { + case 'b': + return (long long)(num * (float)B_MULT); + case 'k': + return (long long)(num * (float)K_MULT); + case 'K': + return (long long)((num * (float)K_MULT) * sizeof(long long)); + case 'm': + return (long long)(num * (float)M_MULT); + case 'M': + return (long long)((num * (float)M_MULT) * sizeof(long long)); + case 'g': + return (long long)(num * (float)G_MULT); + case 'G': + return (long long)((num * (float)G_MULT) * sizeof(long long)); + default: + return -1; + } +} + +#ifdef UNIT_TEST + +main(int argc, char **argv) +{ + int ind; + + if (argc == 1) { + fprintf(stderr, "missing str_to_bytes() parameteres\n"); + exit(1); + } + + for (ind=1; ind +#include /* for string functions */ +#include "string_to_tokens.h" + +int +string_to_tokens(char *arg_string, char *arg_array[], int array_size, char *separator) +{ + int num_toks = 0; /* number of tokens found */ + char *strtok(); + + if (arg_array == NULL || array_size <= 1 || separator == NULL) + return -1; + + /* + * Use strtok() to parse 'arg_string', placing pointers to the + * individual tokens into the elements of 'arg_array'. + */ + if ((arg_array[num_toks] = strtok(arg_string, separator)) == NULL) { + return 0; + } + + for (num_toks=1;num_toks Return No. of hugepages for this systems + * from /proc/meminfo + * hugepages_size() --> Return Hugepages Size for this system + * from /proc/meminfo + */ + +#include +#include +#include + +int get_no_of_hugepages() { + #ifdef __linux__ + FILE *f; + char buf[BUFSIZ]; + + f = popen("grep 'HugePages_Total' /proc/meminfo | cut -d ':' -f2 | tr -d ' \n'", "r"); + if (!f) + tst_brkm(TBROK, NULL, + "Could not get info about Total_Hugepages from /proc/meminfo"); + if (!fgets(buf, 10, f)) { + fclose(f); + tst_brkm(TBROK, NULL, + "Could not read Total_Hugepages from /proc/meminfo"); + } + pclose(f); + return(atoi(buf)); + #else + return -1; + #endif +} + +int get_no_of_free_hugepages() { + #ifdef __linux__ + FILE *f; + char buf[BUFSIZ]; + + f = popen("grep 'HugePages_Free' /proc/meminfo | cut -d ':' -f2 | tr -d ' \n'", "r"); + if (!f) + tst_brkm(TBROK, NULL, + "Could not get info about HugePages_Free from /proc/meminfo"); + if (!fgets(buf, 10, f)) { + fclose(f); + tst_brkm(TBROK, NULL, + "Could not read HugePages_Free from /proc/meminfo"); + } + pclose(f); + return(atoi(buf)); + #else + return -1; + #endif +} + +int hugepages_size() { + #ifdef __linux__ + FILE *f; + char buf[BUFSIZ]; + + f = popen("grep 'Hugepagesize' /proc/meminfo | cut -d ':' -f2 | tr -d 'kB \n'", "r"); + if (!f) + tst_brkm(TBROK, NULL, + "Could not get info about HugePages_Size from /proc/meminfo"); + if (!fgets(buf, 10, f)) { + fclose(f); + tst_brkm(TBROK, NULL, + "Could not read HugePages_Size from /proc/meminfo"); + } + pclose(f); + return(atoi(buf)); + #else + return -1; + #endif +} diff --git a/ltp_framework/lib/system_specific_process_info.c b/ltp_framework/lib/system_specific_process_info.c new file mode 100644 index 0000000..d3c9638 --- /dev/null +++ b/ltp_framework/lib/system_specific_process_info.c @@ -0,0 +1,88 @@ +/* + * + * Copyright (c) International Business Machines Corp., 2009 + * + * 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 + */ + +/* + * DESCRIPTION + * get_max_pids(): Return the maximum number of pids for this system by + * reading /proc/sys/kernel/pid_max + * + * get_free_pids(): Return number of free pids by subtracting the number + * of pids currently used ('ps -eT') from max_pids + */ + + +#include +#include +#include +#include "test.h" + +#define BUFSIZE 512 + +int get_max_pids(void) +{ +#ifdef __linux__ + + FILE *f; + char buf[BUFSIZE]; + + f = fopen("/proc/sys/kernel/pid_max", "r"); + if (!f) { + tst_resm(TBROK, "Could not open /proc/sys/kernel/pid_max"); + return -1; + } + if (!fgets(buf, BUFSIZE, f)) { + fclose(f); + tst_resm(TBROK, "Could not read /proc/sys/kernel/pid_max"); + return -1; + } + fclose(f); + return atoi(buf); +#else + return SHRT_MAX; +#endif +} + + +int get_free_pids(void) +{ + FILE *f; + int rc, used_pids, max_pids; + + f = popen("ps -eT | wc -l", "r"); + if (!f) { + tst_resm(TBROK, "Could not run 'ps' to calculate used " + "pids"); + return -1; + } + rc = fscanf(f, "%i", &used_pids); + pclose(f); + + if (rc != 1 || used_pids < 0) { + tst_resm(TBROK, "Could not read output of 'ps' to " + "calculate used pids"); + return -1; + } + + max_pids = get_max_pids(); + + if (max_pids < 0) + return -1; + + return max_pids - used_pids; +} diff --git a/ltp_framework/lib/tlibio.c b/ltp_framework/lib/tlibio.c new file mode 100644 index 0000000..eaaaaa0 --- /dev/null +++ b/ltp_framework/lib/tlibio.c @@ -0,0 +1,2084 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +/* + * + * Lib i/o + * + * This file contains several functions to doing reads and writes. + * It was written so that a single function could be called in a test + * program and only a io type field value would have to change to + * do different types of io. There is even a couple of functions that + * will allow you to parse a string to determine the iotype. + * + * This file contains functions for writing/reading to/from open files + * Prototypes: + * + * Functions declared in this module - see individual function code for + * usage comments: + * + * int stride_bounds(int offset, int stride, int nstrides, + * int bytes_per_stride, int *min, int *max); + + * int lio_write_buffer(int fd, int method, char *buffer, int size, + * char **errmsg, long wrd); + * int lio_read_buffer(int fd, int method, char *buffer, int size, + * char **errmsg, long wrd); + * + * #ifdef CRAY + * int lio_wait4asyncio(int method, int fd, struct iosw **statptr) + * int lio_check_asyncio(char *io_type, int size, struct iosw *status) + * #endif + * #ifdef sgi + * int lio_wait4asyncio(int method, int fd, aiocb_t *aiocbp) + * int lio_check_asyncio(char *io_type, int size, aiocb_t *aiocbp, int method) + * #endif + * + * int lio_parse_io_arg1(char *string) + * void lio_help1(char *prefix); + * + * int lio_parse_io_arg2(char *string, char **badtoken) + * void lio_help2(char *prefix); + * + * int lio_set_debug(int level); + * + * char Lio_SysCall[]; + * struct lio_info_type Lio_info1[]; + * struct lio_info_type Lio_info2[]; + * + * Author : Richard Logan + * + */ + +#ifdef __linux__ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#define _LARGEFILE64_SOURCE +#endif +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CRAY +#include +#include +#include +#else +/* for linux or sgi */ +#include /* readv(2)/writev(2) */ +#include /* bzero */ +#endif +#if defined(__linux__) || defined(__sun) || defined(__hpux) || defined(_AIX) +#if !defined(UCLINUX) && !defined(__UCLIBC__) +#include +#endif +#endif +#include /* atoi, abs */ + +#include "tlibio.h" /* defines LIO* marcos */ +#include "random_range.h" + +#ifndef PATH_MAX +#define PATH_MAX MAXPATHLEN +#endif + +#if 0 /* disabled until it's needed -- roehrich 6/11/97 */ +#define BUG1_workaround 1 /* Work around a condition where aio_return gives + * a value of zero but there is no errno followup + * and the read/write operation actually did its + * job. spr/pv 705244 + */ +#endif + + +static void lio_async_signal_handler(); +#ifdef sgi +static void lio_async_callback_handler(); +#endif + +/* + * Define the structure as used in lio_parse_arg1 and lio_help1 + */ +struct lio_info_type Lio_info1[] = { + { "s", LIO_IO_SYNC, "sync i/o" }, + { "p", LIO_IO_ASYNC|LIO_WAIT_SIGACTIVE, "async i/o using a loop to wait for a signal" }, + { "b", LIO_IO_ASYNC|LIO_WAIT_SIGPAUSE, "async i/o using pause" }, + { "a", LIO_IO_ASYNC|LIO_WAIT_RECALL, "async i/o using recall/aio_suspend" }, +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + { "r", + LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random sync i/o types and wait methods" }, + { "R", + LIO_RANDOM|LIO_IO_ATYPES|LIO_WAIT_ATYPES, "random i/o types and wait methods" }, +#else + { "r", + LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random i/o types and wait methods" }, + { "R", + LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random i/o types and wait methods" }, +#endif + { "l", LIO_IO_SLISTIO|LIO_WAIT_RECALL, "single stride sync listio" }, + { "L", LIO_IO_ALISTIO|LIO_WAIT_RECALL, "single stride async listio using recall" }, + { "X", LIO_IO_ALISTIO|LIO_WAIT_SIGPAUSE, "single stride async listio using pause" }, + { "v", LIO_IO_SYNCV, "single buffer sync readv/writev" }, + { "P", LIO_IO_SYNCP, "sync pread/pwrite" }, +}; + +/* + * Define the structure used by lio_parse_arg2 and lio_help2 + */ +struct lio_info_type Lio_info2[] = { + { "sync", LIO_IO_SYNC, "sync i/o (read/write)"}, + { "async", LIO_IO_ASYNC, "async i/o (reada/writea/aio_read/aio_write)" }, + { "slistio", LIO_IO_SLISTIO, "single stride sync listio" }, + { "alistio", LIO_IO_ALISTIO, "single stride async listio" }, + { "syncv", LIO_IO_SYNCV, "single buffer sync readv/writev"}, + { "syncp", LIO_IO_SYNCP, "pread/pwrite"}, + { "active", LIO_WAIT_ACTIVE, "spin on status/control values" }, + { "recall", LIO_WAIT_RECALL, "use recall(2)/aio_suspend(3) to wait for i/o to complete" }, + { "sigactive", LIO_WAIT_SIGACTIVE, "spin waiting for signal" }, + { "sigpause", LIO_WAIT_SIGPAUSE, "call pause(2) to wait for signal" }, +/* nowait is a touchy thing, it's an accident that this implementation worked at all. 6/27/97 roehrich */ +/* { "nowait", LIO_WAIT_NONE, "do not wait for async io to complete" },*/ + { "random", LIO_RANDOM, "set random bit" }, + { "randomall", + LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, + "all random i/o types and wait methods (except nowait)" }, +}; + +char Lio_SysCall[PATH_MAX]; /* string containing last i/o system call */ + +static volatile int Received_signal = 0; /* number of signals received */ +static volatile int Rec_signal; +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) +static volatile int Received_callback = 0; /* number of callbacks received */ +static volatile int Rec_callback; +#endif +static char Errormsg[500]; +static int Debug_level = 0; + + + +/*********************************************************************** + * stride_bounds() + * + * Determine the bounds of a strided request, normalized to offset. Returns + * the number of bytes needed to satisfy the request, and optionally sets + * *min and *max to the mininum and maximum bytes referenced, normalized + * around offset. + * + * Returns -1 on error - the only possible error conditions are illegal values + * for nstrides and/or bytes_per_stride - both parameters must be >= 0. + * + * (maule, 11/16/95) + ***********************************************************************/ + +int +stride_bounds(offset, stride, nstrides, bytes_per_stride, min, max) +int offset; +int stride; +int nstrides; +int bytes_per_stride; +int *min; +int *max; +{ + int nbytes, min_byte, max_byte; + + /* + * sanity checks ... + */ + + if (nstrides < 0 || bytes_per_stride < 0) { + return -1; + } + + if (stride == 0) { + stride = bytes_per_stride; + } + + /* + * Determine the # of bytes needed to satisfy the request. This + * value, along with the offset argument, determines the min and max + * bytes referenced. + */ + + + nbytes = abs(stride) * (nstrides-1) + bytes_per_stride; + + if (stride < 0) { + max_byte = offset + bytes_per_stride - 1; + min_byte = max_byte - nbytes + 1; + } else { + min_byte = offset; + max_byte = min_byte + nbytes - 1; + } + + if (min != NULL) { + *min = min_byte; + } + + if (max != NULL) { + *max = max_byte; + } + + return nbytes; +} + +/*********************************************************************** + * This function will allow someone to set the debug level. + ***********************************************************************/ +int +lio_set_debug(level) +{ + int old; + + old = Debug_level; + Debug_level = level; + return old; +} + +/*********************************************************************** + * This function will parse a string and return desired io-method. + * Only the first character of the string is used. + * + * This function does not provide for meaningful option arguments, + * but it supports current growfiles/btlk interface. + * + * (rrl 04/96) + ***********************************************************************/ +int +lio_parse_io_arg1(char *string) +{ + unsigned int ind; + int found=0; + int mask=0; + + /* + * Determine if token is a valid string. + */ + for (ind=0; ind 3) + printf("DEBUG %s/%d: method mask to choose from: %#o\n", __FILE__, __LINE__, method ); + method = lio_random_methods(method); + if (Debug_level > 2) + printf("DEBUG %s/%d: random chosen method %#o\n", __FILE__, __LINE__, method); + } + + if (errmsg != NULL) + *errmsg = Errormsg; + + Rec_signal=Received_signal; /* get the current number of signals received */ +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + Rec_callback=Received_callback; /* get the current number of callbacks received */ +#endif + +#ifdef CRAY + memset(&status, 0x00, sizeof(struct iosw)); + memset(&request, 0x00, sizeof(struct listreq)); + statptr[0] = &status; +#else + /* for linux or sgi */ + memset(&iov, 0x00, sizeof(struct iovec)); + iov.iov_base = buffer; + iov.iov_len = size; +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) +#if defined(sgi) + memset(&aiocbp, 0x00, sizeof(aiocb_t)); +#else + memset(&aiocbp, 0x00, sizeof(struct aiocb)); +#endif + aiocbp.aio_fildes = fd; + aiocbp.aio_nbytes = size; + aiocbp.aio_buf = buffer; +/* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */ + aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE; + aiocbp.aio_sigevent.sigev_signo = 0; +#ifdef sgi + aiocbp.aio_sigevent.sigev_func = NULL; + aiocbp.aio_sigevent.sigev_value.sival_int = 0; +#elif defined(__linux__) && !defined(__UCLIBC__) + aiocbp.aio_sigevent.sigev_notify_function = NULL; + aiocbp.aio_sigevent.sigev_notify_attributes = 0; +#endif + aiolist[0] = &aiocbp; + + if ((ret = lseek( fd, 0, SEEK_CUR )) == -1) { + ret = 0; + /* If there is an error and it is not ESPIPE then kick out the error. + * If the fd is a fifo then we have to make sure that + * lio_random_methods() didn't select pwrite/pread; if it did then + * switch to write/read. + */ + if (errno == ESPIPE) { + if (method & LIO_IO_SYNCP) { + if (omethod & LIO_RANDOM) { + method &= ~LIO_IO_SYNCP; + method |= LIO_IO_SYNC; + if (Debug_level > 2) + printf("DEBUG %s/%d: random chosen method switched to %#o for fifo\n", __FILE__, __LINE__, method ); + } + else if (Debug_level) { + printf("DEBUG %s/%d: pwrite will fail when it writes to a fifo\n", + __FILE__, __LINE__ ); + } + } + /* else: let it ride */ + } + else{ + sprintf(Errormsg, "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s", + __FILE__, __LINE__, fd, errno, strerror(errno)); + return -errno; + } + } +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + poffset = (off64_t)ret; +#endif + aiocbp.aio_offset = ret; + +#endif + + /* + * If the LIO_USE_SIGNAL bit is not set, only use the signal + * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are bit. + * Otherwise there is not necessary a signal handler to trap + * the signal. + */ + if (sig && !(method & LIO_USE_SIGNAL) && + ! (method & LIO_WAIT_SIGTYPES) ) { + + sig=0; /* ignore signal parameter */ + } + +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + if (sig && (method & LIO_WAIT_CBTYPES)) + sig=0; /* ignore signal parameter */ +#endif + + /* + * only setup signal hander if sig was specified and + * a sig wait method was specified. + * Doing this will change the handler for this signal. The + * old signal handler will not be restored. + *** restoring the signal handler could be added *** + */ + + if (sig && (method & LIO_WAIT_SIGTYPES)) { +#ifdef CRAY + sigctl(SCTL_REG, sig, lio_async_signal_handler); +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL; + aiocbp.aio_sigevent.sigev_signo = sig; + sigset(sig, lio_async_signal_handler); +#endif /* sgi */ + } +#if defined(sgi) + else if (method & LIO_WAIT_CBTYPES) { + /* sival_int just has to be something that I can use + * to identify the callback, and "size" happens to be handy... + */ + aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK; + aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler; + aiocbp.aio_sigevent.sigev_value.sival_int = size; + } +#endif +#if defined(__linux__) && !defined(__UCLIBC__) + else if (method & LIO_WAIT_CBTYPES) { + /* sival_int just has to be something that I can use + * to identify the callback, and "size" happens to be handy... + */ + aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD; + aiocbp.aio_sigevent.sigev_notify_function = lio_async_callback_handler; + aiocbp.aio_sigevent.sigev_notify_attributes = (void*)(uintptr_t)size; + } +#endif + /* + * Determine the system call that will be called and produce + * the string of the system call and place it in Lio_SysCall. + * Also update the io_type char pointer to give brief description + * of system call. Execute the system call and check for + * system call failure. If sync i/o, return the number of + * bytes written/read. + */ + + if ((method & LIO_IO_SYNC) || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) { + /* + * write(2) is used if LIO_IO_SYNC bit is set or not none + * of the LIO_IO_TYPES bits are set (default). + */ + + sprintf(Lio_SysCall, + "write(%d, buf, %d)", fd, size); + io_type="write"; + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + while (1) { + if (((ret = write(fd, buffer, size)) == -1) && errno!=EAGAIN && errno!=EINTR) { + sprintf(Errormsg, "%s/%d write(%d, buf, %d) ret:-1, errno=%d %s", + __FILE__, __LINE__, + fd, size, errno, strerror(errno)); + return -errno; + } + + if (ret!=-1) { + if (ret != size) { + sprintf(Errormsg, + "%s/%d write(%d, buf, %d) returned=%d", + __FILE__, __LINE__, + fd, size, ret); + size-=ret; + buffer+=ret; + } + else { + if (Debug_level > 1) + printf("DEBUG %s/%d: write completed without error (ret %d)\n", + __FILE__, __LINE__, ret); + + return ret; + } + } + wait4sync_io(fd, 0); + } + + } + + else if (method & LIO_IO_ASYNC) { +#ifdef CRAY + sprintf(Lio_SysCall, + "writea(%d, buf, %d, &status, %d)", fd, size, sig); + io_type="writea"; + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + sigoff(); + if ((ret = writea(fd, buffer, size, &status, sig)) == -1) { + sprintf(Errormsg, + "%s/%d writea(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s", + __FILE__, __LINE__, + fd, size, sig, errno, strerror(errno)); + sigon(); + return -errno; + } +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + sprintf(Lio_SysCall, + "aio_write(fildes=%d, buf, nbytes=%d, signo=%d)", fd, size, sig); + io_type="aio_write"; + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + if (sig) + sighold( sig ); + if ((ret = aio_write(&aiocbp)) == -1) { + sprintf(Errormsg, + "%s/%d aio_write(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s", + __FILE__, __LINE__, + fd, size, sig, errno, strerror(errno)); + if (sig) + sigrelse( sig ); + return -errno; + } +#endif + } /* LIO_IO_ASYNC */ + + else if (method & LIO_IO_SLISTIO) { +#ifdef CRAY + request.li_opcode = LO_WRITE; + request.li_fildes = fd; + request.li_buf = buffer; + request.li_nbyte = size; + request.li_status = &status; + request.li_signo = sig; + request.li_nstride = 0; + request.li_filstride = 0; + request.li_memstride = 0; + + listio_cmd=LC_WAIT; + io_type="listio(2) sync write"; + + sprintf(Lio_SysCall, + "listio(LC_WAIT, &req, 1) LO_WRITE, fd:%d, nbyte:%d", + fd, size); + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + sigoff(); + if (listio(listio_cmd, &request, 1) == -1) { + sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s", + __FILE__, __LINE__, + Lio_SysCall, fd, size, errno, strerror(errno)); + sigon(); + return -errno; + } + + if (Debug_level > 1) + printf("DEBUG %s/%d: %s did not return -1\n", + __FILE__, __LINE__, Lio_SysCall); + + ret=lio_check_asyncio(io_type, size, &status); + return ret; + +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + + aiocbp.aio_lio_opcode = LIO_WRITE; + listio_cmd=LIO_WAIT; + io_type="lio_listio(3) sync write"; + + sprintf(Lio_SysCall, + "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d, sig:%d", + fd, size, sig ); + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + if (sig) + sighold( sig ); + if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) { + sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s", + __FILE__, __LINE__, + Lio_SysCall, fd, size, errno, strerror(errno)); + if (sig) + sigrelse( sig ); + return -errno; + } + + if (Debug_level > 1) + printf("DEBUG %s/%d: %s did not return -1\n", + __FILE__, __LINE__, Lio_SysCall); + + ret=lio_check_asyncio(io_type, size, &aiocbp, method); + return ret; +#endif + } /* LIO_IO_SLISTIO */ + + else if (method & LIO_IO_ALISTIO) { +#ifdef CRAY + request.li_opcode = LO_WRITE; + request.li_fildes = fd; + request.li_buf = buffer; + request.li_nbyte = size; + request.li_status = &status; + request.li_signo = sig; + request.li_nstride = 0; + request.li_filstride = 0; + request.li_memstride = 0; + + listio_cmd=LC_START; + io_type="listio(2) async write"; + + sprintf(Lio_SysCall, + "listio(LC_START, &req, 1) LO_WRITE, fd:%d, nbyte:%d", + fd, size); + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + sigoff(); + if (listio(listio_cmd, &request, 1) == -1) { + sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s", + __FILE__, __LINE__, + Lio_SysCall, fd, size, errno, strerror(errno)); + sigon(); + return -errno; + } +#endif +#if defined (sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + aiocbp.aio_lio_opcode = LIO_WRITE; + listio_cmd=LIO_NOWAIT; + io_type="lio_listio(3) async write"; + + sprintf(Lio_SysCall, + "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d", + fd, size); + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + if (sig) + sighold( sig ); + if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) { + sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s", + __FILE__, __LINE__, + Lio_SysCall, fd, size, errno, strerror(errno)); + if (sig) + sigrelse( sig ); + return -errno; + } +#endif + }/* LIO_IO_ALISTIO */ + +#ifndef CRAY + else if (method & LIO_IO_SYNCV) { + io_type="writev(2)"; + + sprintf(Lio_SysCall, + "writev(%d, &iov, 1) nbyte:%d", fd, size); + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + if ((ret = writev(fd, &iov, 1)) == -1) { + sprintf(Errormsg, "%s/%d writev(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s", + __FILE__, __LINE__, + fd, size, errno, strerror(errno)); + return -errno; + } + + if (ret != size) { + sprintf(Errormsg, + "%s/%d writev(%d, iov, 1) nbyte:%d returned=%d", + __FILE__, __LINE__, + fd, size, ret); + } + else if (Debug_level > 1) + printf("DEBUG %s/%d: writev completed without error (ret %d)\n", + __FILE__, __LINE__, ret); + + return ret; + } /* LIO_IO_SYNCV */ +#endif + +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + else if (method & LIO_IO_SYNCP) { + io_type="pwrite(2)"; + + sprintf(Lio_SysCall, + "pwrite(%d, buf, %d, %lld)", fd, size, (long long)poffset); + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + if ((ret = pwrite(fd, buffer, size, poffset)) == -1) { + sprintf(Errormsg, "%s/%d pwrite(%d, buf, %d, %lld) ret:-1, errno=%d %s", + __FILE__, __LINE__, + fd, size, (long long)poffset, errno, strerror(errno)); + return -errno; + } + + if (ret != size) { + sprintf(Errormsg, + "%s/%d pwrite(%d, buf, %d, %lld) returned=%d", + __FILE__, __LINE__, + fd, size, (long long)poffset, ret); + } + else if (Debug_level > 1) + printf("DEBUG %s/%d: pwrite completed without error (ret %d)\n", + __FILE__, __LINE__, ret); + + return ret; + } /* LIO_IO_SYNCP */ +#endif + + else { + printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__, __LINE__ ); + return -1; + } + + /* + * wait for async io to complete. + */ +#ifdef CRAY + ret=lio_wait4asyncio(method, fd, statptr); +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + ret=lio_wait4asyncio(method, fd, &aiocbp); +#endif + + /* + * If there was an error waiting for async i/o to complete, + * return the error value (errno) to the caller. + * Note: Errormsg should already have been updated. + */ + if (ret < 0) { + return ret; + } + + /* + * If i/o was not waited for (may not have been completed at this time), + * return the size that was requested. + */ + if (ret == 1) + return size; + + /* + * check that async io was successful. + * Note: if the there was an system call failure, -errno + * was returned and Errormsg should already have been updated. + * If amount i/o was different than size, Errormsg should already + * have been updated but the actual i/o size if returned. + */ + +#ifdef CRAY + ret=lio_check_asyncio(io_type, size, &status); +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + ret=lio_check_asyncio(io_type, size, &aiocbp, method); +#endif + + return ret; +} /* end of lio_write_buffer */ + +/*********************************************************************** + * Generic read function + * This function can be used to do a read using read(2), reada(2), + * aio_read(3), readv(2), pread(2), + * or single stride listio(2)/lio_listio(3). + * By setting the desired bits in the method + * bitmask, the caller can control the type of read and the wait method + * that will be used. If no io type bits are set, read will be used. + * + * If async io was attempted and no wait method bits are set then the + * wait method is: recall(2) for reada(2) and listio(2); aio_suspend(3) for + * aio_read(3) and lio_listio(3). + * + * If multiple wait methods are specified, + * only one wait method will be used. The order is predetermined. + * + * If the call specifies a signal and one of the two signal wait methods, + * a signal handler for the signal is set. This will reset an already + * set handler for this signal. + * + * If the LIO_RANDOM method bit is set, this function will randomly + * choose a io type and wait method from bits in the method argument. + * + * If an error is encountered, an error message will be generated + * in a internal static buffer. If errmsg is not NULL, it will + * be updated to point to the static buffer, allowing the caller + * to print the error message. + * + * Return Value + * If a system call fails, -errno is returned. + * If LIO_WAIT_NONE bit is set, the return value is the return value + * of the system call. + * If the io did not fail, the amount of data written is returned. + * If the size the system call say was written is different + * then what was asked to be written, errmsg is updated for + * this error condition. The return value is still the amount + * the system call says was written. + * + * (rrl 04/96) + ***********************************************************************/ +int +lio_read_buffer(fd, method, buffer, size, sig, errmsg, wrd) +int fd; /* open file descriptor */ +int method; /* contains io type and wait method bitmask */ +char *buffer; /* pointer to buffer */ +int size; /* the size of the io */ +int sig; /* signal to use if async io */ +char **errmsg; /* char pointer that will be updated to point to err message */ +long wrd; /* to allow future features, use zero for now */ +{ + int ret = 0; /* syscall return or used to get random method */ + char *io_type; /* Holds string of type of io */ + int listio_cmd; /* Holds the listio/lio_listio cmd */ + int omethod = method; +#ifdef CRAY + struct listreq request; /* Used when a listio is wanted */ + struct iosw status, *statptr[1]; +#else + /* for linux or sgi */ + struct iovec iov; /* iovec for readv(2) */ +#endif +#ifdef sgi + aiocb_t aiocbp; /* POSIX aio control block */ + aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */ + off64_t poffset; /* pread(2) offset */ +#endif +#if defined (__linux__) && !defined(__UCLIBC__) + struct aiocb aiocbp; /* POSIX aio control block */ + struct aiocb *aiolist[1]; /* list of aio control blocks for lio_listio */ + off64_t poffset; /* pread(2) offset */ +#endif + + /* + * If LIO_RANDOM bit specified, get new method randomly. + */ + if (method & LIO_RANDOM) { + if (Debug_level > 3) + printf("DEBUG %s/%d: method mask to choose from: %#o\n", __FILE__, __LINE__, method ); + method = lio_random_methods(method); + if (Debug_level > 2) + printf("DEBUG %s/%d: random chosen method %#o\n", __FILE__, __LINE__, method); + } + + if (errmsg != NULL) + *errmsg = Errormsg; + + Rec_signal=Received_signal; /* get the current number of signals received */ +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + Rec_callback=Received_callback; /* get the current number of callbacks received */ +#endif + +#ifdef CRAY + memset(&status, 0x00, sizeof(struct iosw)); + memset(&request, 0x00, sizeof(struct listreq)); + statptr[0] = &status; +#else + /* for linux or sgi */ + memset(&iov, 0x00, sizeof(struct iovec)); + iov.iov_base = buffer; + iov.iov_len = size; +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) +#if defined(sgi) + memset(&aiocbp, 0x00, sizeof(aiocb_t)); +#else + memset(&aiocbp, 0x00, sizeof(struct aiocb)); +#endif + aiocbp.aio_fildes = fd; + aiocbp.aio_nbytes = size; + aiocbp.aio_buf = buffer; +/* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */ + aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE; + aiocbp.aio_sigevent.sigev_signo = 0; +#ifdef sgi + aiocbp.aio_sigevent.sigev_func = NULL; + aiocbp.aio_sigevent.sigev_value.sival_int = 0; +#elif defined(__linux__) && !defined(__UCLIBC__) + aiocbp.aio_sigevent.sigev_notify_function = NULL; + aiocbp.aio_sigevent.sigev_notify_attributes = 0; +#endif + aiolist[0] = &aiocbp; + + if ((ret = lseek( fd, 0, SEEK_CUR )) == -1) { + ret = 0; + /* If there is an error and it is not ESPIPE then kick out the error. + * If the fd is a fifo then we have to make sure that + * lio_random_methods() didn't select pwrite/pread; if it did then + * switch to write/read. + */ + if (errno == ESPIPE) { + if (method & LIO_IO_SYNCP) { + if (omethod & LIO_RANDOM) { + method &= ~LIO_IO_SYNCP; + method |= LIO_IO_SYNC; + if (Debug_level > 2) + printf("DEBUG %s/%d: random chosen method switched to %#o for fifo\n", __FILE__, __LINE__, method ); + } + else if (Debug_level) { + printf("DEBUG %s/%d: pread will fail when it reads from a fifo\n", + __FILE__, __LINE__ ); + } + } + /* else: let it ride */ + } + else{ + sprintf(Errormsg, "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s", + __FILE__, __LINE__, fd, errno, strerror(errno)); + return -errno; + } + } +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + poffset = (off64_t)ret; +#endif + aiocbp.aio_offset = ret; + +#endif + + /* + * If the LIO_USE_SIGNAL bit is not set, only use the signal + * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are set. + * Otherwise there is not necessarily a signal handler to trap + * the signal. + */ + if (sig && !(method & LIO_USE_SIGNAL) && + ! (method & LIO_WAIT_SIGTYPES) ) { + + sig=0; /* ignore signal parameter */ + } + +#if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__)) + if (sig && (method & LIO_WAIT_CBTYPES)) + sig=0; /* ignore signal parameter */ +#endif + + /* + * only setup signal hander if sig was specified and + * a sig wait method was specified. + * Doing this will change the handler for this signal. The + * old signal handler will not be restored. + *** restoring the signal handler could be added *** + */ + + if (sig && (method & LIO_WAIT_SIGTYPES)) { +#ifdef CRAY + sigctl(SCTL_REG, sig, lio_async_signal_handler); +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL; + aiocbp.aio_sigevent.sigev_signo = sig; + sigset(sig, lio_async_signal_handler); +#endif /* CRAY */ + } +#if defined(sgi) + else if (method & LIO_WAIT_CBTYPES) { + aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK; + aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler; + /* sival_int just has to be something that I can use + * to identify the callback, and "size" happens to be handy... + */ + aiocbp.aio_sigevent.sigev_value.sival_int = size; + } +#endif +#if defined(__linux__) && !defined(__UCLIBC__) + else if (method & LIO_WAIT_CBTYPES) { + aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD; + aiocbp.aio_sigevent.sigev_notify_function = lio_async_callback_handler; + /* sival_int just has to be something that I can use + * to identify the callback, and "size" happens to be handy... + */ + aiocbp.aio_sigevent.sigev_notify_attributes = (void*)(uintptr_t)size; + } +#endif + + /* + * Determine the system call that will be called and produce + * the string of the system call and place it in Lio_SysCall. + * Also update the io_type char pointer to give brief description + * of system call. Execute the system call and check for + * system call failure. If sync i/o, return the number of + * bytes written/read. + */ + + if ((method & LIO_IO_SYNC) || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) { + /* + * read(2) is used if LIO_IO_SYNC bit is set or not none + * of the LIO_IO_TYPES bits are set (default). + */ + + sprintf(Lio_SysCall, + "read(%d, buf, %d)", fd, size); + io_type="read"; + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + while (1) { + if (((ret = read(fd, buffer, size)) == -1) && errno!=EINTR && errno!=EAGAIN) { + sprintf(Errormsg, "%s/%d read(%d, buf, %d) ret:-1, errno=%d %s", + __FILE__, __LINE__, + fd, size, errno, strerror(errno)); + return -errno; + } + + if (ret==0) return 0; + if (ret!=-1) { + if (ret != size) { + sprintf(Errormsg, + "%s/%d read(%d, buf, %d) returned=%d", + __FILE__, __LINE__, + fd, size, ret); + size-=ret; + buffer+=ret; + } + else { + if (Debug_level > 1) + printf("DEBUG %s/%d: read completed without error (ret %d)\n", + __FILE__, __LINE__, ret); + + return ret; + } + } + wait4sync_io(fd, 1); + } + + } + + else if (method & LIO_IO_ASYNC) { +#ifdef CRAY + sprintf(Lio_SysCall, + "reada(%d, buf, %d, &status, %d)", fd, size, sig); + io_type="reada"; + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + sigoff(); + if ((ret = reada(fd, buffer, size, &status, sig)) == -1) { + sprintf(Errormsg, + "%s/%d reada(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s", + __FILE__, __LINE__, + fd, size, sig, errno, strerror(errno)); + sigon(); + return -errno; + } +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + sprintf(Lio_SysCall, + "aio_read(fildes=%d, buf, nbytes=%d, signo=%d)", fd, size, sig); + io_type="aio_read"; + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + if (sig) + sighold( sig ); + if ((ret = aio_read(&aiocbp)) == -1) { + sprintf(Errormsg, + "%s/%d aio_read(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s", + __FILE__, __LINE__, + fd, size, sig, errno, strerror(errno)); + if (sig) + sigrelse( sig ); + return -errno; + } +#endif + } /* LIO_IO_ASYNC */ + + else if (method & LIO_IO_SLISTIO) { +#ifdef CRAY + request.li_opcode = LO_READ; + request.li_fildes = fd; + request.li_buf = buffer; + request.li_nbyte = size; + request.li_status = &status; + request.li_signo = sig; + request.li_nstride = 0; + request.li_filstride = 0; + request.li_memstride = 0; + + listio_cmd=LC_WAIT; + io_type="listio(2) sync read"; + + sprintf(Lio_SysCall, + "listio(LC_WAIT, &req, 1) LO_READ, fd:%d, nbyte:%d", + fd, size); + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + sigoff(); + if (listio(listio_cmd, &request, 1) == -1) { + sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s", + __FILE__, __LINE__, + Lio_SysCall, fd, size, errno, strerror(errno)); + sigon(); + return -errno; + } + + if (Debug_level > 1) + printf("DEBUG %s/%d: %s did not return -1\n", + __FILE__, __LINE__, Lio_SysCall); + + ret=lio_check_asyncio(io_type, size, &status); + return ret; +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + aiocbp.aio_lio_opcode = LIO_READ; + listio_cmd=LIO_WAIT; + io_type="lio_listio(3) sync read"; + + sprintf(Lio_SysCall, + "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d", + fd, size); + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + if (sig) + sighold( sig ); + if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) { + sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s", + __FILE__, __LINE__, + Lio_SysCall, fd, size, errno, strerror(errno)); + if (sig) + sigrelse( sig ); + return -errno; + } + + if (Debug_level > 1) + printf("DEBUG %s/%d: %s did not return -1\n", + __FILE__, __LINE__, Lio_SysCall); + + ret=lio_check_asyncio(io_type, size, &aiocbp, method); + return ret; +#endif + }/* LIO_IO_SLISTIO */ + + else if (method & LIO_IO_ALISTIO) { +#ifdef CRAY + request.li_opcode = LO_READ; + request.li_fildes = fd; + request.li_buf = buffer; + request.li_nbyte = size; + request.li_status = &status; + request.li_signo = sig; + request.li_nstride = 0; + request.li_filstride = 0; + request.li_memstride = 0; + + listio_cmd=LC_START; + io_type="listio(2) async read"; + + sprintf(Lio_SysCall, + "listio(LC_START, &req, 1) LO_READ, fd:%d, nbyte:%d", + fd, size); + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + sigoff(); + if (listio(listio_cmd, &request, 1) == -1) { + sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s", + __FILE__, __LINE__, + Lio_SysCall, fd, size, errno, strerror(errno)); + sigon(); + return -errno; + } +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + aiocbp.aio_lio_opcode = LIO_READ; + listio_cmd=LIO_NOWAIT; + io_type="lio_listio(3) async read"; + + sprintf(Lio_SysCall, + "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d", + fd, size); + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + + if (sig) + sighold( sig ); + if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) { + sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s", + __FILE__, __LINE__, + Lio_SysCall, fd, size, errno, strerror(errno)); + if (sig) + sigrelse( sig ); + return -errno; + } +#endif + } /* LIO_IO_ALISTIO */ + +#ifndef CRAY + else if (method & LIO_IO_SYNCV) { + io_type="readv(2)"; + + sprintf(Lio_SysCall, + "readv(%d, &iov, 1) nbyte:%d", fd, size); + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + if ((ret = readv(fd, &iov, 1)) == -1) { + sprintf(Errormsg, "%s/%d readv(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s", + __FILE__, __LINE__, + fd, size, errno, strerror(errno)); + return -errno; + } + + if (ret != size) { + sprintf(Errormsg, + "%s/%d readv(%d, iov, 1) nbyte:%d returned=%d", + __FILE__, __LINE__, + fd, size, ret); + } + else if (Debug_level > 1) + printf("DEBUG %s/%d: readv completed without error (ret %d)\n", + __FILE__, __LINE__, ret); + + return ret; + } /* LIO_IO_SYNCV */ +#endif + +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + else if (method & LIO_IO_SYNCP) { + io_type="pread(2)"; + + sprintf(Lio_SysCall, + "pread(%d, buf, %d, %lld)", fd, size, (long long)poffset); + + if (Debug_level) { + printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall); + } + if ((ret = pread(fd, buffer, size, poffset)) == -1) { + sprintf(Errormsg, "%s/%d pread(%d, buf, %d, %lld) ret:-1, errno=%d %s", + __FILE__, __LINE__, + fd, size, (long long)poffset, errno, strerror(errno)); + return -errno; + } + + if (ret != size) { + sprintf(Errormsg, + "%s/%d pread(%d, buf, %d, %lld) returned=%d", + __FILE__, __LINE__, + fd, size, (long long)poffset, ret); + } + else if (Debug_level > 1) + printf("DEBUG %s/%d: pread completed without error (ret %d)\n", + __FILE__, __LINE__, ret); + + return ret; + } /* LIO_IO_SYNCP */ +#endif + + else { + printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__, __LINE__ ); + return -1; + } + + /* + * wait for async io to complete. + * Note: Sync io should have returned prior to getting here. + */ +#ifdef CRAY + ret=lio_wait4asyncio(method, fd, statptr); +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + ret=lio_wait4asyncio(method, fd, &aiocbp); +#endif + + /* + * If there was an error waiting for async i/o to complete, + * return the error value (errno) to the caller. + * Note: Errormsg should already have been updated. + */ + if (ret < 0) { + return ret; + } + + /* + * If i/o was not waited for (may not have been completed at this time), + * return the size that was requested. + */ + if (ret == 1) + return size; + + /* + * check that async io was successful. + * Note: if the there was an system call failure, -errno + * was returned and Errormsg should already have been updated. + * If amount i/o was different than size, Errormsg should already + * have been updated but the actual i/o size if returned. + */ + +#ifdef CRAY + ret=lio_check_asyncio(io_type, size, &status); +#endif +#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) + ret=lio_check_asyncio(io_type, size, &aiocbp, method); +#endif + + return ret; +} /* end of lio_read_buffer */ + + +#if !defined(__sun) && !defined(__hpux) && !defined(_AIX) +/*********************************************************************** + * This function will check that async io was successful. + * It can also be used to check sync listio since it uses the + * same method. + * + * Return Values + * If status.sw_error is set, -status.sw_error is returned. + * Otherwise sw_count's field value is returned. + * + * (rrl 04/96) + ***********************************************************************/ +#ifdef CRAY +int lio_check_asyncio(char *io_type, int size, struct iosw *status) +#elif defined(sgi) + int lio_check_asyncio(char *io_type, int size, aiocb_t *aiocbp, int method) +#elif defined(__linux__) && !defined(__UCLIBC__) + int lio_check_asyncio(char *io_type, int size, struct aiocb *aiocbp, int method) +{ + int ret; + +#ifdef CRAY + if (status->sw_error) { + sprintf(Errormsg, + "%s/%d %s, sw_error set = %d %s, sw_count = %d", + __FILE__, __LINE__, io_type, + status->sw_error, strerror(status->sw_error), status->sw_count); + return -status->sw_error; + } + else if (status->sw_count != size) { + sprintf(Errormsg, + "%s/%d %s, sw_count not as expected(%d), but actual:%d", + __FILE__, __LINE__, io_type, + size, status->sw_count); + } + else if (Debug_level > 1) { + printf("DEBUG %s/%d: %s completed without error (sw_error == 0, sw_count == %d)\n", + __FILE__, __LINE__, io_type, status->sw_count); + } + + return status->sw_count; + +#else + + int cnt = 1; + + /* The I/O may have been synchronous with signal completion. It doesn't + * make sense, but the combination could be generated. Release the + * completion signal here otherwise it'll hang around and bite us + * later. + */ + if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL) + sigrelse( aiocbp->aio_sigevent.sigev_signo ); + + ret = aio_error( aiocbp ); + + while (ret == EINPROGRESS) { + ret = aio_error( aiocbp ); + ++cnt; + } + if (cnt > 1) { + sprintf(Errormsg, + "%s/%d %s, aio_error had to loop on EINPROGRESS, cnt=%d; random method %#o; sigev_notify=%s", + __FILE__, __LINE__, io_type, cnt, method, + (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" : + aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" : +#ifdef SIGEV_CALLBACK + aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" : +#endif + aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD ? "thread" : + "unknown") ); + return -ret; + } + + if (ret != 0) { + sprintf(Errormsg, + "%s/%d %s, aio_error = %d %s; random method %#o", + __FILE__, __LINE__, io_type, + ret, strerror(ret), + method ); + return -ret; + } + ret = aio_return( aiocbp ); + if (ret != size) { + sprintf(Errormsg, + "%s/%d %s, aio_return not as expected(%d), but actual:%d", + __FILE__, __LINE__, io_type, + size, ret); + +#ifdef BUG1_workaround + if (ret == 0) { + ret = size; + if (Debug_level > 1) { + printf("WARN %s/%d: %s completed with bug1_workaround (aio_error == 0, aio_return now == %d)\n", + __FILE__, __LINE__, io_type, ret); + } + } +#endif /* BUG1_workaround */ + + } + else if (Debug_level > 1) { + printf("DEBUG %s/%d: %s completed without error (aio_error == 0, aio_return == %d)\n", + __FILE__, __LINE__, io_type, ret); + } + + return ret; + +#endif +} /* end of lio_check_asyncio */ +#endif + +/*********************************************************************** + * + * This function will wait for async io to complete. + * If multiple wait methods are specified, the order is predetermined + * to LIO_WAIT_RECALL, + * LIO_WAIT_ACTIVE, LIO_WAIT_SIGPAUSE, LIO_WAIT_SIGACTIVE, + * then LIO_WAIT_NONE. + * + * If no wait method was specified the default wait method is: recall(2) + * or aio_suspend(3), as appropriate. + * + * Return Values + * <0: errno of failed recall + * 0 : async io was completed + * 1 : async was not waited for, io may not have completed. + * + * (rrl 04/96) + ***********************************************************************/ +#ifdef CRAY +int lio_wait4asyncio(int method, int fd, struct iosw **statptr) +#elif defined(sgi) + int lio_wait4asyncio(int method, int fd, aiocb_t *aiocbp) +#elif defined(__linux__) && !defined(__UCLIBC__) + int lio_wait4asyncio(int method, int fd, struct aiocb *aiocbp) +{ + int cnt; +#ifdef sgi + int ret; + const aiocb_t *aioary[1]; +#endif +#if defined(__linux__)&& !defined(__UCLIBC__) + int ret; + const struct aiocb *aioary[1]; +#endif + + if ((method & LIO_WAIT_RECALL) +#if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__)) + || (method & LIO_WAIT_CBSUSPEND) + || (method & LIO_WAIT_SIGSUSPEND) +#endif + || ((method & LIO_WAIT_TYPES) == 0) ) { + /* + * If method has LIO_WAIT_RECALL bit set or method does + * not have any wait method bits set (default), use recall/aio_suspend. + */ +#ifdef CRAY + if (Debug_level > 2) + printf("DEBUG %s/%d: wait method : recall\n", __FILE__, __LINE__); + sigon(); + if (recall(fd, 1, statptr)) { + sprintf(Errormsg, "%s/%d recall(%d, 1, stat) failed, errno:%d %s", + __FILE__, __LINE__, + fd, errno, strerror(errno)); + return -errno; + } +#else + if (Debug_level > 2) + printf("DEBUG %s/%d: wait method : aio_suspend, sigev_notify=%s\n", __FILE__, __LINE__, + (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" : + aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" : +#ifdef SIGEV_CALLBACK + aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" : +#endif + aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD ? "thread" : + "unknown") ); + + aioary[0] = aiocbp; + ret = aio_suspend( aioary, 1, NULL ); + if ((ret == -1) && (errno == EINTR)) { + if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL) { + if (Debug_level > 2) { + printf("DEBUG %s/%d: aio_suspend received EINTR, sigev_notify=SIGEV_SIGNAL -- ok\n", + __FILE__, __LINE__ ); + } + } + else { + sprintf(Errormsg, "%s/%d aio_suspend received EINTR, sigev_notify=%s, not ok\n", + __FILE__, __LINE__, + (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" : + aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" : +#ifdef SIGEV_CALLBACK + aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" : +#endif + aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD ? "thread" : + "unknown") ); + return -errno; + } + } + else if (ret) { + sprintf(Errormsg, "%s/%d aio_suspend(fildes=%d, aioary, 1, NULL) failed, errno:%d %s", + __FILE__, __LINE__, + fd, errno, strerror(errno)); + return -errno; + } +#endif + + } else if (method & LIO_WAIT_ACTIVE) { + if (Debug_level > 2) + printf("DEBUG %s/%d: wait method : active\n", __FILE__, __LINE__); +#ifdef CRAY + sigon(); + /* + * loop until sw_flag, sw_count or sw_error field elements + * change to non-zero. + */ + cnt=0; + while ((*statptr)->sw_flag == 0 && + (*statptr)->sw_count == 0 && + (*statptr)->sw_error == 0 ) { + cnt++; + } +#else + /* loop while aio_error() returns EINPROGRESS */ + cnt=0; + while (1) { + ret = aio_error( aiocbp ); + if ((ret == 0) || (ret != EINPROGRESS)) { + break; + } + ++cnt; + } + +#endif + if (Debug_level > 5 && cnt && (cnt % 50) == 0) + printf("DEBUG %s/%d: wait active cnt = %d\n", + __FILE__, __LINE__, cnt); + + } else if (method & LIO_WAIT_SIGPAUSE) { + if (Debug_level > 2) + printf("DEBUG %s/%d: wait method : sigpause\n", __FILE__, __LINE__); +#ifdef sgi + /* note: don't do the sigon() for CRAY in this case. why? -- roehrich 6/11/97 */ + if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL) + sigrelse( aiocbp->aio_sigevent.sigev_signo ); + else { + printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n", __FILE__, __LINE__ ); + return -1; + } +#endif + pause(); + + } else if (method & LIO_WAIT_SIGACTIVE) { + if (Debug_level > 2) + printf("DEBUG %s/%d: wait method : sigactive\n", __FILE__, __LINE__); +#ifdef CRAY + sigon(); +#else + if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL) + sigrelse( aiocbp->aio_sigevent.sigev_signo ); + else { + printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n", __FILE__, __LINE__ ); + return -1; + } +#endif + /* loop waiting for signal */ + while (Received_signal == Rec_signal) { +#ifdef CRAY + sigon(); +#else + sigrelse( aiocbp->aio_sigevent.sigev_signo ); +#endif + } + + } else if (method & LIO_WAIT_NONE) { + if (Debug_level > 2) + printf("DEBUG %s/%d: wait method : none\n", __FILE__, __LINE__); + /* It's broken because the aiocb/iosw is an automatic variable in + * lio_{read,write}_buffer, so when the function returns and the + * I/O completes there will be nowhere to write the I/O status. + * It doesn't cause a problem on unicos--probably because of some + * compiler quirk, or an accident. It causes POSIX async I/O + * to core dump some threads. spr/pv 705909. 6/27/97 roehrich + */ + sprintf(Errormsg, "%s/%d LIO_WAIT_NONE was selected (this is broken)\n", + __FILE__, __LINE__ ); +#ifdef CRAY + sigon(); +#endif +/* return 1;*/ + return -1; + } + else { + if (Debug_level > 2) + printf("DEBUG %s/%d: no wait method was chosen\n", __FILE__, __LINE__ ); + return -1; + } + + return 0; + +} /* end of lio_wait4asyncio */ + +#endif /* ifndef linux */ +#endif + +#if UNIT_TEST +/*********************************************************************** + * The following code is provided as unit test. + * Just define add "-DUNIT_TEST=1" to the cc line. + * + * (rrl 04/96) + ***********************************************************************/ +struct unit_info_t { + int method; + int sig; + char *str; +} Unit_info[] = { + { LIO_IO_SYNC, 0, "sync io" }, + { LIO_IO_SYNCV, 0, "sync readv/writev" }, + { LIO_IO_SYNCP, 0, "sync pread/pwrite" }, + { LIO_IO_ASYNC, 0, "async io, def wait" }, + { LIO_IO_SLISTIO, 0, "sync listio" }, + { LIO_IO_ALISTIO, 0, "async listio, def wait" }, + { LIO_IO_ASYNC|LIO_WAIT_ACTIVE, 0, "async active" }, + { LIO_IO_ASYNC|LIO_WAIT_RECALL, 0, "async recall/suspend" }, + { LIO_IO_ASYNC|LIO_WAIT_SIGPAUSE, SIGUSR1, "async sigpause" }, + { LIO_IO_ASYNC|LIO_WAIT_SIGACTIVE, SIGUSR1, "async sigactive" }, + { LIO_IO_ALISTIO|LIO_WAIT_ACTIVE, 0, "async listio active" }, + { LIO_IO_ALISTIO|LIO_WAIT_RECALL, 0, "async listio recall" }, + { LIO_IO_ALISTIO|LIO_WAIT_SIGACTIVE, SIGUSR1, "async listio sigactive" }, + { LIO_IO_ALISTIO|LIO_WAIT_SIGPAUSE, SIGUSR1, "async listio sigpause" }, + { LIO_IO_ASYNC, SIGUSR2, "async io, def wait, sigusr2" }, + { LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2" }, +}; + +int +main(argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + + int fd; + char *err; + char buffer[4096]; + int size=4096; + int ret; + int ind; + int iter=3; + int method; + int exit_status = 0; + int c; + int i; + char *symbols = NULL; + int die_on_err = 0; + + while ((c = getopt(argc,argv,"s:di:")) != -1) { + switch(c) { + case 's': symbols = optarg; break; + case 'd': ++die_on_err; break; + case 'i': iter = atoi(optarg); break; + } + } + + if ((fd=open("unit_test_file", O_CREAT|O_RDWR|O_TRUNC, 0777)) == -1) { + perror("open(unit_test_file, O_CREAT|O_RDWR|O_TRUNC, 0777) failed"); + exit(1); + } + + Debug_level=9; + + if (symbols != NULL) { + if ((method=lio_parse_io_arg2(symbols, &err)) == -1) { + printf("lio_parse_io_arg2(%s, &err) failed, bad token starting at %s\n", + symbols, err); + if (die_on_err) + exit(1); + } + else + printf("lio_parse_io_arg2(%s, &err) returned %#o\n", symbols, method); + + exit_status = 0; + for (ind=0; ind < iter; ind++) { + memset( buffer, 'A', 4096 ); + if (lseek(fd, 0, 0) == -1) { + printf("lseek(fd,0,0), %d, failed, errno %d\n", + __LINE__, errno ); + ++exit_status; + } + if ((ret=lio_write_buffer(fd, method, buffer, + size, SIGUSR1, &err, 0)) != size ) { + printf("lio_write_buffer returned -1, err = %s\n", err); + } else + printf("lio_write_buffer returned %d\n", ret); + + memset( buffer, 'B', 4096 ); + if (lseek(fd, 0, 0) == -1) { + printf("lseek(fd,0,0), %d, failed, errno %d\n", + __LINE__, errno ); + ++exit_status; + } + if ((ret=lio_read_buffer(fd, method, buffer, + size, SIGUSR2, &err, 0)) != size ) { + printf("lio_read_buffer returned -1, err = %s\n", err); + } else + printf("lio_read_buffer returned %d\n", ret); + + for (i = 0; i < 4096; ++i) { + if (buffer[i] != 'A') { + printf(" buffer[%d] = %d\n", i, buffer[i] ); + ++exit_status; + break; + } + } + + if (exit_status) + exit(exit_status); + + } + + unlink("unit_test_file"); + exit(0); + } + + for (ind=0; ind < sizeof(Unit_info)/sizeof(struct unit_info_t); ind++) { + + printf("\n********* write %s ***************\n", Unit_info[ind].str); + if (lseek(fd, 0, 0) == -1) { + printf("lseek(fd,0,0), %d, failed, errno %d\n", + __LINE__, errno ); + ++exit_status; + } + + memset( buffer, 'A', 4096 ); + if ((ret=lio_write_buffer(fd, Unit_info[ind].method, buffer, + size, Unit_info[ind].sig, &err, 0)) != size ) { + printf(">>>>> lio_write_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n", + Unit_info[ind].method, size, Unit_info[ind].sig, err); + ++exit_status; + if (die_on_err) + exit(exit_status); + } else{ + printf("lio_write_buffer returned %d\n", ret); + } + + printf("\n********* read %s ***************\n", Unit_info[ind].str); + if (lseek(fd, 0, 0) == -1) { + printf("lseek(fd,0,0), %d, failed, errno %d\n", + __LINE__, errno ); + ++exit_status; + } + memset( buffer, 'B', 4096 ); + if ((ret=lio_read_buffer(fd, Unit_info[ind].method, buffer, + size, Unit_info[ind].sig, &err, 0)) != size ) { + printf(">>>>> lio_read_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n", + Unit_info[ind].method, size, Unit_info[ind].sig, err); + ++exit_status; + if (die_on_err) + exit(exit_status); + } else { + printf("lio_read_buffer returned %d\n", ret); + } + + for (i = 0; i < 4096; ++i) { + if (buffer[i] != 'A') { + printf(" buffer[%d] = %d\n", i, buffer[i] ); + ++exit_status; + if (die_on_err) + exit(exit_status); + break; + } + } + + fflush(stdout); + fflush(stderr); + sleep(1); + + } + + unlink("unit_test_file"); + + exit(exit_status); +} +#endif diff --git a/ltp_framework/lib/tst_cwd_has_free.c b/ltp_framework/lib/tst_cwd_has_free.c new file mode 100644 index 0000000..791df09 --- /dev/null +++ b/ltp_framework/lib/tst_cwd_has_free.c @@ -0,0 +1,22 @@ +/* + * AUTHOR + * Ricky Ng-Adam , 2005-01-01 + * + * DESCRIPTION + * Check if there is enough blocks to fill number of KiB specified + * If current directory has enough blocks, return 1 + * If current directory has NOT enough blocks, return 0 + * + * + */ +#include + +int +tst_cwd_has_free(int required_kib) +{ + struct statfs sf; + statfs(".", &sf); + + /* check that we have enough blocks to create swap file */ + return ((float)sf.f_bfree)/(1024/sf.f_bsize) >= required_kib?1:0; +} \ No newline at end of file diff --git a/ltp_framework/lib/tst_is_cwd.c b/ltp_framework/lib/tst_is_cwd.c new file mode 100644 index 0000000..636aaca --- /dev/null +++ b/ltp_framework/lib/tst_is_cwd.c @@ -0,0 +1,52 @@ +/* + * Michal Simek , 2009-08-03 - ramfs + * Kumar Gala , 2007-11-14 - nfs + * Ricky Ng-Adam , 2005-01-01 - tmpfs + * + * DESCRIPTION + * Check if current directory is on a tmpfs/nfs/ramfs filesystem + * If current directory is tmpfs/nfs/ramfs, return 1 + * If current directory is NOT tmpfs/nfs/ramfs, return 0 + */ + +#include + +#define TMPFS_MAGIC 0x01021994 /* man 2 statfs */ +int tst_is_cwd_tmpfs(void) +{ + struct statfs sf; + statfs(".", &sf); + + /* Verify that the file is not on a tmpfs (in-memory) filesystem */ + return (sf.f_type == TMPFS_MAGIC); +} + +#define NFS_MAGIC 0x6969 /* man 2 statfs */ +int tst_is_cwd_nfs(void) +{ + struct statfs sf; + statfs(".", &sf); + + /* Verify that the file is not on a nfs filesystem */ + return (sf.f_type == NFS_MAGIC); +} + +#define V9FS_MAGIC 0x01021997 /* kernel-source/include/linux/magic.h */ +int tst_is_cwd_v9fs(void) +{ + struct statfs sf; + statfs(".", &sf); + + /* Verify that the file is not on a nfs filesystem */ + return (sf.f_type == V9FS_MAGIC); +} + +#define RAMFS_MAGIC 0x858458f6 +int tst_is_cwd_ramfs(void) +{ + struct statfs sf; + statfs(".", &sf); + + /* Verify that the file is not on a ramfs (in-memory) filesystem */ + return (sf.f_type == RAMFS_MAGIC); +} diff --git a/ltp_framework/lib/tst_kvercmp.c b/ltp_framework/lib/tst_kvercmp.c new file mode 100644 index 0000000..f132164 --- /dev/null +++ b/ltp_framework/lib/tst_kvercmp.c @@ -0,0 +1,68 @@ +/* + * + * Copyright (c) International Business Machines Corp., 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * + * AUTHOR + * Paul Larson + * + * DESCRIPTION + * Compare a given kernel version against the current kernel version. + * If they are the same - return 0 + * If the argument is > current kernel version - return positive int + * If the argument is < current kernel version - return negative int + * + */ + + +#include +#include +#include +#include + +void get_kver(int *k1, int *k2, int *k3) +{ + struct utsname uval; + char *kver; + char *r1, *r2, *r3; +#if !defined(linux) + extern char *strsep(); /* shut up some compilers */ +#endif + + uname(&uval); + kver = uval.release; + r1 = strsep(&kver, "."); + r2 = strsep(&kver, "."); + r3 = strsep(&kver, "."); + + *k1 = atoi(r1); + *k2 = atoi(r2); + *k3 = atoi(r3); +} + +int tst_kvercmp(int r1, int r2, int r3) { + int a1, a2, a3; + int testver, currver; + + get_kver(&a1, &a2, &a3); + testver = (r1 << 16) + (r2 << 8) + r3; + currver = (a1 << 16) + (a2 << 8) + a3; + + return currver - testver; +} \ No newline at end of file diff --git a/ltp_framework/lib/tst_res.c b/ltp_framework/lib/tst_res.c new file mode 100644 index 0000000..f958279 --- /dev/null +++ b/ltp_framework/lib/tst_res.c @@ -0,0 +1,812 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2009 Cyril Hrubis chrubis@suse.cz + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ + + +/* $Id: tst_res.c,v 1.14 2009/12/01 08:57:20 yaberauneya Exp $ */ + +/********************************************************** + * + * OS Testing - Silicon Graphics, Inc. + * + * FUNCTION NAME : + * tst_res() - Print result message (include file contents) + * tst_resm() - Print result message + * tst_brk() - Print result message (include file contents) + * and break remaining test cases + * tst_brkm() - Print result message and break remaining test + * cases + * tst_flush() - Print any messages pending in the output stream + * tst_exit() - Exit test with a meaningful exit value. + * tst_environ() - Keep results coming to original stdout + * + * FUNCTION TITLE : Standard automated test result reporting mechanism + * + * SYNOPSIS: + * #include "test.h" + * + * void tst_res(ttype, fname, tmesg [,arg]...) + * int ttype; + * char *fname; + * char *tmesg; + * + * void tst_resm(ttype, tmesg [,arg]...) + * int ttype; + * char *tmesg; + * + * void tst_brk(ttype, fname, cleanup, tmesg, [,argv]...) + * int ttype; + * char *fname; + * void (*cleanup)(); + * char *tmesg; + * + * void tst_brkm(ttype, cleanup, tmesg [,arg]...) + * int ttype; + * void (*cleanup)(); + * char *tmesg; + * + * void tst_flush() + * + * void tst_exit() + * + * int tst_environ() + * + * AUTHOR : Kent Rogers (from Dave Fenner's original) + * + * CO-PILOT : Rich Logan + * + * DATE STARTED : 05/01/90 (rewritten 1/96) + * + * MAJOR CLEANUPS BY : Cyril Hrubis + * + * DESCRIPTION + * See the man page(s). + * + *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ + +#include +#include +#include +#include +#include +#include +#include +#include "test.h" +#include "usctest.h" + +/* Break bad habits. */ +#ifdef GARRETT_IS_A_PEDANTIC_BASTARD +pid_t spawned_program_pid; +#endif + +#define VERBOSE 1 /* flag values for the T_mode variable */ +#define NOPASS 3 +#define DISCARD 4 + +#define MAXMESG 80 /* max length of internal messages */ +#define USERMESG 2048 /* max length of user message */ +#define TRUE 1 +#define FALSE 0 + +/* + * EXPAND_VAR_ARGS - Expand the variable portion (arg_fmt) of a result + * message into the specified string. + * + * NOTE (garrcoop): arg_fmt _must_ be the last element in each function + * argument list that employs this. + */ +#define EXPAND_VAR_ARGS(buf, arg_fmt, buf_len) do {\ + va_list ap; \ + assert(arg_fmt != NULL); \ + va_start(ap, arg_fmt); \ + vsnprintf(buf, buf_len, arg_fmt, ap); \ + va_end(ap); \ + assert(strlen(buf) > 0); \ +} while (0) + +/* + * Define local function prototypes. + */ +static void check_env(void); +static void tst_condense(int tnum, int ttype, char *tmesg); +static void tst_print(char *tcid, int tnum, int ttype, char *tmesg); +static void cat_file(char *filename); + +/* + * Define some static/global variables. + */ +static FILE *T_out = NULL; /* tst_res() output file descriptor */ +static char *File; /* file whose contents is part of result */ +static int T_exitval = 0; /* exit value used by tst_exit() */ +static int T_mode = VERBOSE; /* flag indicating print mode: VERBOSE, */ + /* NOPASS, DISCARD */ + +static char Warn_mesg[MAXMESG]; /* holds warning messages */ + +/* + * These are used for condensing output when NOT in verbose mode. + */ +static int Buffered = FALSE; /* TRUE if condensed output is currently */ + /* buffered (i.e. not yet printed) */ +static char *Last_tcid; /* previous test case id */ +static int Last_num; /* previous test case number */ +static int Last_type; /* previous test result type */ +static char *Last_mesg; /* previous test result message */ + + +/* + * These globals may be externed by the test. + */ +int Tst_count = 0; /* current count of test cases executed; NOTE: */ + /* Tst_count may be externed by other programs */ + +/* + * These globals must be defined in the test. + */ +extern char *TCID; /* Test case identifier from the test source */ +extern int TST_TOTAL; /* Total number of test cases from the test */ + /* source */ + +struct pair { + const char *name; + int val; +}; +#define PAIR(def) [def] = { .name = #def, .val = def, }, +const char *pair_lookup(struct pair *pair, int pair_size, int idx) +{ + if (idx < 0 || idx >= pair_size || pair[idx].name == NULL) + return "???"; + return pair[idx].name; +} +#define pair_lookup(pair, idx) pair_lookup(pair, ARRAY_SIZE(pair), idx) + +/* + * strttype() - convert a type result to the human readable string + */ +const char *strttype(int ttype) +{ + struct pair ttype_pairs[] = { + PAIR(TPASS) + PAIR(TFAIL) + PAIR(TBROK) + PAIR(TRETR) + PAIR(TCONF) + PAIR(TWARN) + PAIR(TINFO) + }; + return pair_lookup(ttype_pairs, TTYPE_RESULT(ttype)); +} + +/* + * strerrnodef() - convert an errno value to its C define + */ +static const char *strerrnodef(int err) +{ + struct pair errno_pairs[] = { + PAIR(EPERM) + PAIR(ENOENT) + PAIR(ESRCH) + PAIR(EINTR) + PAIR(EIO) + PAIR(ENXIO) + PAIR(E2BIG) + PAIR(ENOEXEC) + PAIR(EBADF) + PAIR(ECHILD) + PAIR(EAGAIN) + PAIR(ENOMEM) + PAIR(EACCES) + PAIR(EFAULT) + PAIR(ENOTBLK) + PAIR(EBUSY) + PAIR(EEXIST) + PAIR(EXDEV) + PAIR(ENODEV) + PAIR(ENOTDIR) + PAIR(EISDIR) + PAIR(EINVAL) + PAIR(ENFILE) + PAIR(EMFILE) + PAIR(ENOTTY) + PAIR(ETXTBSY) + PAIR(EFBIG) + PAIR(ENOSPC) + PAIR(ESPIPE) + PAIR(EROFS) + PAIR(EMLINK) + PAIR(EPIPE) + PAIR(EDOM) + PAIR(ERANGE) + PAIR(ENAMETOOLONG) + }; + return pair_lookup(errno_pairs, err); +} + +/* + * tst_res() - Main result reporting function. Handle test information + * appropriately depending on output display mode. Call + * tst_condense() or tst_print() to actually print results. + * All result functions (tst_resm(), tst_brk(), etc.) + * eventually get here to print the results. + */ +void tst_res(int ttype, char *fname, char *arg_fmt, ...) +{ + char tmesg[USERMESG]; + int ttype_result = TTYPE_RESULT(ttype); + +#if DEBUG + printf("IN tst_res; Tst_count = %d\n", Tst_count); + fflush(stdout); +#endif + + EXPAND_VAR_ARGS(tmesg, arg_fmt, USERMESG); + + /* + * Save the test result type by ORing ttype into the current exit + * value (used by tst_exit()). + */ + T_exitval |= ttype_result; + + /* + * Unless T_out has already been set by tst_environ(), make tst_res() + * output go to standard output. + */ + if (T_out == NULL) + T_out = stdout; + + /* + * Check TOUTPUT environment variable (if first time) and set T_mode + * flag. + */ + check_env(); + + if (fname != NULL && access(fname, F_OK) == 0) + File = fname; + + /* + * Set the test case number and print the results, depending on the + * display type. + */ + if (ttype_result == TWARN || ttype_result == TINFO) { + tst_print(TCID, 0, ttype, tmesg); + } else { + if (Tst_count < 0) + tst_print(TCID, 0, TWARN, + "tst_res(): Tst_count < 0 is not valid"); + + /* + * Process each display type. + */ + switch (T_mode) { + case DISCARD: + break; + case NOPASS: /* filtered by tst_print() */ + tst_condense(Tst_count+1, ttype, tmesg); + break; + default: /* VERBOSE */ + tst_print(TCID, Tst_count+1, ttype, tmesg); + break; + } + + Tst_count++; + } + +} + + +/* + * tst_condense() - Handle test cases in NOPASS mode (i.e. + * buffer the current result and print the last result + * if different than the current). If a file was + * specified, print the current result and do not + * buffer it. + */ +static void tst_condense(int tnum, int ttype, char *tmesg) +{ + char *file; + int ttype_result = TTYPE_RESULT(ttype); + +#if DEBUG + printf( "IN tst_condense: tcid = %s, tnum = %d, ttype = %d, " + "tmesg = %s\n", + TCID, tnum, ttype, tmesg); + fflush(stdout); +#endif + + /* + * If this result is the same as the previous result, return. + */ + if (Buffered == TRUE) { + if (strcmp(Last_tcid, TCID) == 0 && Last_type == ttype_result && + strcmp(Last_mesg, tmesg) == 0 && File == NULL) + return; + + /* + * This result is different from the previous result. First, + * print the previous result. + */ + file = File; + File = NULL; + tst_print(Last_tcid, Last_num, Last_type, Last_mesg); + free(Last_tcid); + free(Last_mesg); + File = file; + } + + /* + * If a file was specified, print the current result since we have no + * way of retaining the file contents for comparing with future + * results. Otherwise, buffer the current result info for next time. + */ + if (File != NULL) { + tst_print(TCID, tnum, ttype, tmesg); + Buffered = FALSE; + } else { + Last_tcid = (char *)malloc(strlen(TCID) + 1); + strcpy(Last_tcid, TCID); + Last_num = tnum; + Last_type = ttype_result; + Last_mesg = (char *)malloc(strlen(tmesg) + 1); + strcpy(Last_mesg, tmesg); + Buffered = TRUE; + } +} + + +/* + * tst_flush() - Print any messages pending because due to tst_condense, + * and flush T_out. + */ +void tst_flush(void) +{ +#if DEBUG + printf("IN tst_flush\n"); + fflush(stdout); +#endif + + /* + * Print out last line if in NOPASS mode. + */ + if (Buffered == TRUE && T_mode == NOPASS) { + tst_print(Last_tcid, Last_num, Last_type, Last_mesg); + Buffered = FALSE; + } + + fflush(T_out); +} + + +/* + * tst_print() - Print a line to the output stream. + */ +static void tst_print(char *tcid, int tnum, int ttype, char *tmesg) +{ + /* + * avoid unintended side effects from failures with fprintf when + * calling write(2), et all. + */ + int err = errno; + const char *type; + int ttype_result = TTYPE_RESULT(ttype); + +#ifdef GARRETT_IS_A_PEDANTIC_BASTARD + /* Don't execute these APIs unless you have the same pid as main! */ + if (spawned_program_pid != 0) { + /* + * Die quickly and noisily so people get the cluebat that the + * test needs to be fixed. These APIs should _not_ be called + * from forked processes because of the fact that it can confuse + * end-users with printouts, cleanup will potentially blow away + * directories and/or files still in use introducing + * non-determinism, etc. + * + * assert will not return (by design in accordance with POSIX + * 1003.1) if the assertion fails. Read abort(3) for more + * details. So don't worry about saving / restoring the signal + * handler, unless you have a buggy OS that you've hacked 15 + * different ways to Sunday. + */ + assert(spawned_program_pid == getpid()); + } +#endif + +#if DEBUG + printf("IN tst_print: tnum = %d, ttype = %d, tmesg = %s\n", + tnum, ttype, tmesg); + fflush(stdout); +#endif + + /* + * Save the test result type by ORing ttype into the current exit value + * (used by tst_exit()). This is already done in tst_res(), but is + * also done here to catch internal warnings. For internal warnings, + * tst_print() is called directly with a case of TWARN. + */ + T_exitval |= ttype_result; + + /* + * If output mode is DISCARD, or if the output mode is NOPASS and this + * result is not one of FAIL, BROK, or WARN, just return. This check + * is necessary even though we check for DISCARD mode inside of + * tst_res(), since occasionally we get to this point without going + * through tst_res() (e.g. internal TWARN messages). + */ + if (T_mode == DISCARD || (T_mode == NOPASS && ttype_result != TFAIL && + ttype_result != TBROK && ttype_result != TWARN)) + return; + + /* + * Build the result line and print it. + */ + type = strttype(ttype); + if (T_mode == VERBOSE) { + fprintf(T_out, "%-8s %4d %s : %s", tcid, tnum, type, tmesg); + } else { + fprintf(T_out, "%-8s %4d %s : %s", + tcid, tnum, type, tmesg); + } + if (ttype & TERRNO) { + fprintf(T_out, ": errno=%s(%i): %s", strerrnodef(err), + err, strerror(err)); + } + if (ttype & TTERRNO) { + fprintf(T_out, ": TEST_ERRNO=%s(%i): %s", + strerrnodef(TEST_ERRNO), (int)TEST_ERRNO, + strerror(TEST_ERRNO)); + } + fprintf(T_out, "\n"); + + /* + * If tst_res() was called with a file, append file contents to the + * end of last printed result. + */ + if (File != NULL) + cat_file(File); + + File = NULL; +} + + +/* + * check_env() - Check the value of the environment variable TOUTPUT and + * set the global variable T_mode. The TOUTPUT environment + * variable should be set to "VERBOSE", "NOPASS", or "DISCARD". + * If TOUTPUT does not exist or is not set to a valid value, the + * default is "VERBOSE". + */ +static void check_env(void) +{ + static int first_time = 1; + char *value; + +#if DEBUG + printf("IN check_env\n"); + fflush(stdout); +#endif + + if (!first_time) + return; + + first_time = 0; + + /* BTOUTPUT not defined, use default */ + if ((value = getenv(TOUTPUT)) == NULL) { + T_mode = VERBOSE; + return; + } + + if (strcmp(value, TOUT_NOPASS_S) == 0) { + T_mode = NOPASS; + return; + } + + if (strcmp(value, TOUT_DISCARD_S) == 0) { + T_mode = DISCARD; + return; + } + + /* default */ + T_mode = VERBOSE; + return; +} + + +/* + * tst_exit() - Call exit() with the value T_exitval, set up by + * tst_res(). T_exitval has a bit set for most of the + * result types that were seen (including TPASS, TFAIL, + * TBROK, TWARN, TCONF). Also, print the last result (if + * necessary) before exiting. + */ +void tst_exit(void) +{ +#if DEBUG + printf("IN tst_exit\n"); fflush(stdout); + fflush(stdout); +#endif + + /* Call tst_flush() flush any output in the buffer. */ + tst_flush(); + + /* Mask out TRETR, TINFO, and TCONF results from the exit status. */ + exit(T_exitval & ~(TRETR | TINFO | TCONF)); +} + + +/* + * tst_environ() - Preserve the tst_res() output location, despite any + * changes to stdout. + */ +int tst_environ(void) +{ + if ((T_out = fdopen(dup(fileno(stdout)), "w")) == NULL) + return -1; + else + return 0; +} + + +/* + * Make tst_brk reentrant so that one can call the SAFE_* macros from within + * user-defined cleanup functions. + */ +static int tst_brk_entered = 0; + +/* + * tst_brk() - Fail or break current test case, and break the remaining + * tests cases. + */ +void tst_brk(int ttype, char *fname, void (*func)(void), char *arg_fmt, ...) +{ + char tmesg[USERMESG]; + int ttype_result = TTYPE_RESULT(ttype); + +#if DEBUG + printf("IN tst_brk\n"); fflush(stdout); + fflush(stdout); +#endif + + EXPAND_VAR_ARGS(tmesg, arg_fmt, USERMESG); + + /* + * Only FAIL, BROK, CONF, and RETR are supported by tst_brk(). + */ + if (ttype_result != TFAIL && ttype_result != TBROK && + ttype_result != TCONF && ttype_result != TRETR) { + sprintf(Warn_mesg, "%s: Invalid Type: %d. Using TBROK", + __func__, ttype_result); + tst_print(TCID, 0, TWARN, Warn_mesg); + /* Keep TERRNO, TTERRNO, etc. */ + ttype = (ttype & ~ttype_result) | TBROK; + } + + tst_res(ttype, fname, "%s", tmesg); + if (tst_brk_entered == 0) { + if (ttype_result == TCONF) + tst_res(ttype, NULL, + "Remaining cases not appropriate for " + "configuration"); + else if (ttype_result == TRETR) + tst_res(ttype, NULL, "Remaining cases retired"); + else if (ttype_result == TBROK) + tst_res(TBROK, NULL, "Remaining cases broken"); + } + + /* + * If no cleanup function was specified, just return to the caller. + * Otherwise call the specified function. + */ + if (func != NULL) { + tst_brk_entered++; + (*func)(); + tst_brk_entered--; + } + if (tst_brk_entered == 0) + tst_exit(); + +} + +/* + * tst_resm() - Interface to tst_res(), with no filename. + */ +void tst_resm(int ttype, char *arg_fmt, ...) +{ + char tmesg[USERMESG]; + +#if DEBUG + printf("IN tst_resm\n"); fflush(stdout); + fflush(stdout); +#endif + + EXPAND_VAR_ARGS(tmesg, arg_fmt, USERMESG); + + tst_res(ttype, NULL, "%s", tmesg); +} + + +/* + * tst_brkm() - Interface to tst_brk(), with no filename. + */ +void tst_brkm(int ttype, void (*func)(void), char *arg_fmt, ...) +{ + char tmesg[USERMESG]; + +#if DEBUG + printf("IN tst_brkm\n"); fflush(stdout); + fflush(stdout); +#endif + + EXPAND_VAR_ARGS(tmesg, arg_fmt, USERMESG); + + tst_brk(ttype, NULL, func, "%s", tmesg); +} + + +/* + * tst_require_root() - Test for root permissions and abort if not. + */ +void tst_require_root(void (*func)(void)) +{ + if (geteuid() != 0) + tst_brkm(TCONF, func, "Test needs to be run as root"); +} + + +/* + * cat_file() - Print the contents of a file to standard out. + */ +static void cat_file(char *filename) +{ + FILE *fp; + int b_read, b_written; + char buffer[BUFSIZ]; + +#if DEBUG + printf("IN cat_file\n"); fflush(stdout); +#endif + + if ((fp = fopen(filename, "r")) == NULL) { + sprintf(Warn_mesg, + "tst_res(): fopen(%s, \"r\") failed; errno = %d: %s", + filename, errno, strerror(errno)); + tst_print(TCID, 0, TWARN, Warn_mesg); + return; + } + + errno = 0; + + while ((b_read = fread(buffer, 1, BUFSIZ, fp)) != 0) { + if ((b_written = fwrite(buffer, 1, b_read, T_out)) != b_read) { + sprintf(Warn_mesg, + "tst_res(): While trying to cat \"%s\", " + "fwrite() wrote only %d of %d bytes", + filename, b_written, b_read); + tst_print(TCID, 0, TWARN, Warn_mesg); + break; + } + } + + if (!feof(fp)) { + sprintf(Warn_mesg, + "tst_res(): While trying to cat \"%s\", fread() " + "failed, errno = %d: %s", + filename, errno, strerror(errno)); + tst_print(TCID, 0, TWARN, Warn_mesg); + } + + if (fclose(fp) != 0) { + sprintf(Warn_mesg, + "tst_res(): While trying to cat \"%s\", fclose() " + "failed, errno = %d: %s", + filename, errno, strerror(errno)); + tst_print(TCID, 0, TWARN, Warn_mesg); + } +} + + +#ifdef UNIT_TEST +/**************************************************************************** + * Unit test code: Takes input from stdin and can make the following + * calls: tst_res(), tst_resm(), tst_brk(), tst_brkm(), + * tst_flush_buf(), tst_exit(). + ****************************************************************************/ +int TST_TOTAL = 10; +char *TCID = "TESTTCID"; + +#define RES "tst_res.c UNIT TEST message; ttype = %d; contents of \"%s\":" +#define RESM "tst_res.c UNIT TEST message; ttype = %d" + +int main(void) +{ + int ttype; + char chr; + char fname[MAXMESG]; + + printf("UNIT TEST of tst_res.c. Options for ttype:\n\ + -1 : call tst_exit()\n\ + -2 : call tst_flush()\n\ + -3 : call tst_brk()\n\ + -4 : call tst_res()\n\ + %2i : call tst_res(TPASS, ...)\n\ + %2i : call tst_res(TFAIL, ...)\n\ + %2i : call tst_res(TBROK, ...)\n\ + %2i : call tst_res(TWARN, ...)\n\ + %2i : call tst_res(TRETR, ...)\n\ + %2i : call tst_res(TINFO, ...)\n\ + %2i : call tst_res(TCONF, ...)\n\n", + TPASS, TFAIL, TBROK, TWARN, TRETR, TINFO, TCONF); + + while (1) { + printf("Enter ttype (-5,-4,-3,-2,-1,%i,%i,%i,%i,%i,%i,%i): ", + TPASS, TFAIL, TBROK, TWARN, TRETR, TINFO, TCONF); + scanf("%d%c", &ttype, &chr); + + switch (ttype) { + case -1: + tst_exit(); + break; + + case -2: + tst_flush(); + break; + + case -3: + printf("Enter the current type (%i=FAIL, %i=BROK, %i=RETR, %i=CONF): ", + TFAIL, TBROK, TRETR, TCONF); + scanf("%d%c", &ttype, &chr); + printf("Enter file name ( for none): "); + gets(fname); + if (strcmp(fname, "") == 0) + tst_brkm(ttype, tst_exit, RESM, ttype); + else + tst_brk(ttype, fname, tst_exit, RES, ttype, fname); + break; + + case -4: + printf("Enter the current type (%i,%i,%i,%i,%i,%i,%i): ", + TPASS, TFAIL, TBROK, TWARN, TRETR, TINFO, TCONF); + scanf("%d%c", &ttype, &chr); + default: + printf("Enter file name ( for none): "); + gets(fname); + + if (strcmp(fname, "") == 0) + tst_resm(ttype, RESM, ttype); + else + tst_res(ttype, fname, RES, ttype, fname); + break; + } + + } +} + +#endif /* UNIT_TEST */ diff --git a/ltp_framework/lib/tst_sig.c b/ltp_framework/lib/tst_sig.c new file mode 100644 index 0000000..53181bf --- /dev/null +++ b/ltp_framework/lib/tst_sig.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ + +/* $Id: tst_sig.c,v 1.13 2009/08/28 09:29:01 vapier Exp $ */ + +/***************************************************************************** + OS Testing - Silicon Graphics, Inc. + + FUNCTION IDENTIFIER : tst_sig Set up for unexpected signals. + + AUTHOR : David D. Fenner + + CO-PILOT : Bill Roske + + DATE STARTED : 06/06/90 + + This module may be linked with c-modules requiring unexpected + signal handling. The parameters to tst_sig are as follows: + + fork_flag - set to FORK or NOFORK depending upon whether the + calling program executes a fork() system call. It + is normally the case that the calling program treats + SIGCLD as an expected signal if fork() is being used. + + handler - a pointer to the unexpected signal handler to + be executed after an unexpected signal has been + detected. If handler is set to DEF_HANDLER, a + default handler is used. This routine should be + declared as function returning an int. + + cleanup - a pointer to a cleanup routine to be executed + by the unexpected signal handler before tst_exit is + called. This parameter is set to NULL if no cleanup + routine is required. An external variable, T_cleanup + is set so that other user-defined handlers have + access to the cleanup routine. This routine should be + declared as returning type void. + +***************************************************************************/ + +#include +#include +#include +#include +#include "test.h" + +#define MAXMESG 150 /* size of mesg string sent to tst_res */ + +void (*T_cleanup) (); /* pointer to cleanup function */ + +/**************************************************************************** + * STD_COPIES is defined in parse_opts.c but is externed here in order to + * test whether SIGCHILD should be ignored or not. + ***************************************************************************/ +extern int STD_COPIES; + +static void def_handler(); /* default signal handler */ +static void (*tst_setup_signal(int, void (*)(int))) (int); + +/**************************************************************************** + * tst_sig() : set-up to catch unexpected signals. fork_flag is set to NOFORK + * if SIGCLD is to be an "unexpected signal", otherwise it is set to + * FORK. cleanup points to a cleanup routine to be executed before + * tst_exit is called (cleanup is set to NULL if no cleanup is desired). + * handler is a pointer to the signal handling routine (if handler is + * set to NULL, a default handler is used). + ***************************************************************************/ + +void tst_sig(int fork_flag, void (*handler) (), void (*cleanup) ()) +{ + int sig; +#ifdef _SC_SIGRT_MIN + long sigrtmin, sigrtmax; +#endif + + /* + * save T_cleanup and handler function pointers + */ + T_cleanup = cleanup; /* used by default handler */ + + if (handler == DEF_HANDLER) { + /* use default handler */ + handler = def_handler; + } +#ifdef _SC_SIGRT_MIN + sigrtmin = sysconf(_SC_SIGRT_MIN); + sigrtmax = sysconf(_SC_SIGRT_MAX); +#endif + + /* + * now loop through all signals and set the handlers + */ + + for (sig = 1; sig < NSIG; sig++) { + /* + * SIGKILL is never unexpected. + * SIGCLD is only unexpected when + * no forking is being done. + * SIGINFO is used for file quotas and should be expected + */ + +#ifdef _SC_SIGRT_MIN + if (sig >= sigrtmin && sig <= sigrtmax) + continue; +#endif + + switch (sig) { + case SIGKILL: + case SIGSTOP: + case SIGCONT: +#if !defined(_SC_SIGRT_MIN) && defined(__SIGRTMIN) && defined(__SIGRTMAX) + /* Ignore all real-time signals */ + case __SIGRTMIN: + case __SIGRTMIN + 1: + case __SIGRTMIN + 2: + case __SIGRTMIN + 3: + case __SIGRTMIN + 4: + case __SIGRTMIN + 5: + case __SIGRTMIN + 6: + case __SIGRTMIN + 7: + case __SIGRTMIN + 8: + case __SIGRTMIN + 9: + case __SIGRTMIN + 10: + case __SIGRTMIN + 11: + case __SIGRTMIN + 12: + case __SIGRTMIN + 13: + case __SIGRTMIN + 14: + case __SIGRTMIN + 15: +/* __SIGRTMIN is 37 on HPPA rather than 32 * + * as on i386, etc. */ +#if !defined(__hppa__) + case __SIGRTMAX - 15: + case __SIGRTMAX - 14: + case __SIGRTMAX - 13: + case __SIGRTMAX - 12: + case __SIGRTMAX - 11: +#endif + case __SIGRTMAX - 10: + case __SIGRTMAX - 9: + case __SIGRTMAX - 8: + case __SIGRTMAX - 7: + case __SIGRTMAX - 6: + case __SIGRTMAX - 5: + case __SIGRTMAX - 4: + case __SIGRTMAX - 3: + case __SIGRTMAX - 2: + case __SIGRTMAX - 1: + case __SIGRTMAX: +#endif +#ifdef CRAY + case SIGINFO: + case SIGRECOVERY: /* allow chkpnt/restart */ +#endif /* CRAY */ + +#ifdef SIGSWAP + case SIGSWAP: +#endif /* SIGSWAP */ + +#ifdef SIGCKPT + case SIGCKPT: +#endif +#ifdef SIGRESTART + case SIGRESTART: +#endif + /* + * pthread-private signals SIGPTINTR and SIGPTRESCHED. + * Setting a handler for these signals is disallowed when + * the binary is linked against libpthread. + */ +#ifdef SIGPTINTR + case SIGPTINTR: +#endif /* SIGPTINTR */ +#ifdef SIGPTRESCHED + case SIGPTRESCHED: +#endif /* SIGPTRESCHED */ +#ifdef _SIGRESERVE + case _SIGRESERVE: +#endif +#ifdef _SIGDIL + case _SIGDIL: +#endif +#ifdef _SIGCANCEL + case _SIGCANCEL: +#endif +#ifdef _SIGGFAULT + case _SIGGFAULT: +#endif + break; + + case SIGCLD: + if (fork_flag == FORK || STD_COPIES > 1) + continue; + + default: + if (tst_setup_signal(sig, handler) == SIG_ERR) + tst_resm(TWARN|TERRNO, + "signal failed for signal %d", sig); + break; + } +#ifdef __sgi + /* On irix (07/96), signal() fails when signo is 33 or higher */ + if (sig + 1 >= 33) + break; +#endif /* __sgi */ + + } /* endfor */ +} + +/**************************************************************************** + * def_handler() : default signal handler that is invoked when + * an unexpected signal is caught. + ***************************************************************************/ + +static void def_handler(int sig) +{ + /* + * Break remaining test cases, do any cleanup, then exit + */ + tst_brkm(TBROK, T_cleanup, + "unexpected signal %d received (pid = %d).", sig, getpid()); +} + +/* + * tst_setup_signal - A function like signal(), but we have + * control over its personality. + */ +static void (*tst_setup_signal(int sig, void (*handler) (int))) (int) +{ + struct sigaction my_act, old_act; + int ret; + + my_act.sa_handler = handler; + my_act.sa_flags = SA_RESTART; + sigemptyset(&my_act.sa_mask); + + ret = sigaction(sig, &my_act, &old_act); + + if (ret == 0) + return old_act.sa_handler; + else + return SIG_ERR; +} \ No newline at end of file diff --git a/ltp_framework/lib/tst_tmpdir.c b/ltp_framework/lib/tst_tmpdir.c new file mode 100644 index 0000000..d112e3e --- /dev/null +++ b/ltp_framework/lib/tst_tmpdir.c @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ + +/* $Id: tst_tmpdir.c,v 1.14 2009/07/20 10:59:32 vapier Exp $ */ + +/********************************************************** + * + * OS Testing - Silicon Graphics, Inc. + * + * FUNCTION NAME : tst_tmpdir, tst_rmdir + * + * FUNCTION TITLE : Create/remove a testing temp dir + * + * SYNOPSIS: + * void tst_tmpdir(); + * void tst_rmdir(); + * + * AUTHOR : Dave Fenner + * + * INITIAL RELEASE : UNICOS 8.0 + * + * DESCRIPTION + * tst_tmpdir() is used to create a unique, temporary testing + * directory, and make it the current working directory. + * tst_rmdir() is used to remove the directory created by + * tst_tmpdir(). + * + * Setting the env variable "TDIRECTORY" will override the creation + * of a new temp dir. The directory specified by TDIRECTORY will + * be used as the temporary directory, and no removal will be done + * in tst_rmdir(). + * + * RETURN VALUE + * Neither tst_tmpdir() or tst_rmdir() has a return value. + * + *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test.h" +#include "rmobj.h" + +/* + * Define some useful macros. + */ +#define DIR_MODE (S_IRWXU|S_IRWXG|S_IRWXO) + +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif + +/* + * Define function prototypes. + */ +static void tmpdir_cleanup(void); + +/* + * Define global variables. + */ +extern char *TCID; /* defined/initialized in main() */ +static char *TESTDIR = NULL; /* the directory created */ + +/* + * Return a copy of the test temp directory as seen by LTP. This is for + * path-oriented tests like chroot, etc, that may munge the path a bit. + * + * FREE VARIABLE AFTER USE IF IT IS REUSED! + */ +char * +get_tst_tmpdir(void) +{ + /* Smack the user for calling things out of order. */ + if (TESTDIR == NULL) + tst_brkm(TBROK, NULL, "you must call tst_tmpdir() first"); + return strdup(TESTDIR); +} + +/* + * tst_tmpdir() - Create a unique temporary directory and chdir() to it. + * It expects the caller to have defined/initialized the + * TCID/TST_TOTAL global variables. The TESTDIR global + * variable will be set to the directory that gets used + * as the testing directory. + * + * NOTE: This function must be called BEFORE any activity + * that would require CLEANUP. If tst_tmpdir() fails, it + * cleans up afer itself and calls tst_exit() (i.e. does + * not return). + */ +void tst_tmpdir(void) +{ + char template[PATH_MAX]; + int no_cleanup = 0; /* !0 means TDIRECTORY env var was set */ + char *env_tmpdir; /* temporary storage for TMPDIR env var */ + /* This is an AWFUL hack to figure out if mkdtemp() is available */ +#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2,2) +#define HAVE_MKDTEMP +#endif + + /* + * If the TDIRECTORY env variable is not set, a temp dir will be + * created. + */ + if ((TESTDIR = getenv(TDIRECTORY)) != NULL) { + /* + * The TDIRECTORY env. variable is set, so no temp dir is created. + */ + if (mkdir(TESTDIR, DIR_MODE) == -1 && errno != EEXIST) { + tst_brkm(TBROK, NULL, "mkdir(%s, %o) failed", + TESTDIR, DIR_MODE); + } + /* + * Try to create the directory if it does not exist already; + * user might forget to create one before exporting TDIRECTORY. + */ + no_cleanup++; +#if UNIT_TEST + printf("TDIRECTORY env var is set\n"); +#endif + } else { + /* + * Create a template for the temporary directory. Use the + * environment variable TMPDIR if it is available, otherwise + * use our default TEMPDIR. + */ + if ((env_tmpdir = getenv("TMPDIR"))) { + snprintf(template, PATH_MAX, "%s/%.3sXXXXXX", env_tmpdir, TCID); + } else { + snprintf(template, PATH_MAX, "%s/%.3sXXXXXX", TEMPDIR, TCID); + } + +#ifdef HAVE_MKDTEMP + /* Make the temporary directory in one shot using mkdtemp. */ + if (mkdtemp(template) == NULL) + tst_brkm(TBROK|TERRNO, tmpdir_cleanup, + "%s: mkdtemp(%s) failed", __func__, template); + if ((TESTDIR = strdup(template)) == NULL) { + tst_brkm(TBROK|TERRNO, tmpdir_cleanup, + "%s: strdup(%s) failed", __func__, template); + } +#else + int tfd; + + /* Make the template name, then the directory */ + if ((tfd = mkstemp(template)) == -1) + tst_brkm(TBROK|TERRNO, tmpdir_cleanup, + "%s: mkstemp(%s) failed", __func__, template); + if (close(tfd) == -1) { + tst_brkm(TBROK|TERRNO, tmpdir_cleanup, + "%s: close() failed", __func__); + } + if (unlink(template) == -1) { + tst_brkm(TBROK|TERRNO, tmpdir_cleanup, + "%s: unlink(%s) failed", __func__, template); + } + if ((TESTDIR = strdup(template)) == NULL) { + tst_brkm(TBROK|TERRNO, tmpdir_cleanup, + "%s: strdup(%s) failed", __func__, template); + } + if (mkdir(TESTDIR, DIR_MODE)) { + /* + * If we start failing with EEXIST, wrap this section in + * a loop so we can try again. + * + * XXX (garrcoop): why? Hacking around broken + * filesystems should not be done. + */ + tst_brkm(TBROK|TERRNO, tmpdir_cleanup, + "%s: mkdir(%s, %#o) failed", + __func__, TESTDIR, DIR_MODE); + } +#endif + + if (chown(TESTDIR, -1, getgid()) == -1) + tst_brkm(TBROK|TERRNO, tmpdir_cleanup, + "chown(%s, -1, %d) failed", TESTDIR, getgid()); + if (chmod(TESTDIR, DIR_MODE) == -1) + tst_brkm(TBROK|TERRNO, tmpdir_cleanup, + "chmod(%s, %#o) failed", TESTDIR, DIR_MODE); + } + +#if UNIT_TEST + printf("TESTDIR = %s\n", TESTDIR); +#endif + + /* + * Change to the temporary directory. If the chdir() fails, issue + * TBROK messages for all test cases, attempt to remove the + * directory (if it was created), and exit. If the removal also + * fails, also issue a TWARN message. + */ + if (chdir(TESTDIR) == -1) { + tst_brkm(TBROK|TERRNO, NULL, "%s: chdir(%s) failed", + __func__, TESTDIR); + + /* Try to remove the directory */ + if (!no_cleanup && rmdir(TESTDIR) == -1) { + tst_resm(TWARN|TERRNO, "%s: rmdir(%s) failed", + __func__, TESTDIR); + } + + tmpdir_cleanup(); + } + +#if UNIT_TEST + printf("CWD is %s\n", getcwd(NULL, PATH_MAX)); +#endif + +} /* tst_tmpdir() */ + + +/* + * + * tst_rmdir() - Recursively remove the temporary directory created by + * tst_tmpdir(). This function is intended ONLY as a + * companion to tst_tmpdir(). If the TDIRECTORY + * environment variable is set, no cleanup will be + * attempted. + */ +void tst_rmdir(void) +{ + struct stat buf1; + struct stat buf2; + char current_dir[PATH_MAX]; + char *errmsg; + char *parent_dir; + char *tdirectory; + + /* + * If the TDIRECTORY env variable is set, this indicates that no + * temp dir was created by tst_tmpdir(). Thus no cleanup will be + * necessary. + */ + if ((tdirectory = getenv(TDIRECTORY)) != NULL) { +#if UNIT_TEST + printf("\"TDIRECORY\" env variable is set; no cleanup was performed\n"); +#endif + return; + } + + /* + * Check that TESTDIR is not NULL. + */ + if (TESTDIR == NULL) { + tst_resm(TWARN, + "%s: TESTDIR was NULL; no removal attempted", __func__); + return; + } + + if ((parent_dir = malloc(PATH_MAX)) == NULL) { + /* Make sure that we exit quickly and noisily. */ + tst_brkm(TBROK|TERRNO, NULL, + "%s: malloc(%d) failed", __func__, PATH_MAX); + } + + /* + * Check that the value of TESTDIR is not "*" or "/". These could + * have disastrous effects in a test run by root. + */ + /* XXX: a temp directory that's '/' seems stupid and dangerous anyways. */ + if (stat(TESTDIR, &buf1) == 0 && stat("/", &buf2) == 0 && + buf1.st_ino == buf2.st_ino) { + tst_resm(TWARN, "%s: will not remove /", __func__); + return; + } + + /* + * XXX: this just reeks of bad programming; all shell characters should + * be escaped in invocations of rm(1)/rmdir(1). + */ + if (strchr(TESTDIR, '*') != NULL) { + tst_resm(TWARN, "%s: will not remove *", __func__); + return; + } + + /* + * Get the directory name of TESTDIR. If TESTDIR is a relative path, + * get full path. + */ + if (TESTDIR[0] != '/') { + if (getcwd(current_dir, PATH_MAX) == NULL) + strncpy(parent_dir, TESTDIR, sizeof(parent_dir)); + else + sprintf(parent_dir, "%s/%s", current_dir, TESTDIR); + } else { + strcpy(parent_dir, TESTDIR); + } + if ((parent_dir = dirname(parent_dir)) == NULL) { + tst_resm(TWARN|TERRNO, "%s: dirname failed", __func__); + return; + } + + /* + * Change directory to parent_dir (The dir above TESTDIR). + */ + if (chdir(parent_dir) != 0) { + tst_resm(TWARN|TERRNO, + "%s: chdir(%s) failed\nAttempting to remove temp dir " + "anyway", + __func__, parent_dir); + } + + /* + * Attempt to remove the "TESTDIR" directory, using rmobj(). + */ + if (rmobj(TESTDIR, &errmsg) == -1) + tst_resm(TWARN, "%s: rmobj(%s) failed: %s", + __func__, TESTDIR, errmsg); + +} /* tst_rmdir() */ + + +/* + * tmpdir_cleanup(void) - This function is used when tst_tmpdir() + * encounters an error, and must cleanup and exit. + * It prints a warning message via tst_resm(), and + * then calls tst_exit(). + */ +static void +tmpdir_cleanup(void) +{ + tst_brkm(TWARN, NULL, + "%s: no user cleanup function called before exiting", __func__); +} + + +#ifdef UNIT_TEST +/**************************************************************************** + * Unit test code: Takes input from stdin and can make the following + * calls: tst_tmpdir(), tst_rmdir(). + ****************************************************************************/ +extern int TST_TOTAL; /* defined/initialized in main() */ + +int TST_TOTAL = 10; +char *TCID = "TESTTCID"; + +main() +{ + int option; + char *chrptr; + + printf("UNIT TEST of tst_tmpdir.c. Options to try:\n\ + -1 : call tst_exit()\n\ + 0 : call tst_tmpdir()\n\ + 1 : call tst_rmdir()\n\n"); + + while (1) { + printf("Enter options (-1, 0, 1): "); + (void)scanf("%d%c", &option, &chrptr); + + switch (option) { + case -1: + tst_exit(); + break; + + case 0: + tst_tmpdir(); + break; + + case 1: + tst_rmdir(); + break; + } /* switch() */ + } /* while () */ +} +#endif /* UNIT_TEST */ diff --git a/ltp_framework/lib/write_log.c b/ltp_framework/lib/write_log.c new file mode 100644 index 0000000..ef560e7 --- /dev/null +++ b/ltp_framework/lib/write_log.c @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + */ +/* + * This module contains code for logging writes to files, and for + * perusing the resultant logfile. The main intent of all this is + * to provide a 'write history' of a file which can be examined to + * judge the state of a file (ie. whether it is corrupted or not) based + * on the write activity. + * + * The main abstractions available to the user are the wlog_file, and + * the wlog_rec. A wlog_file is a handle encapsulating a write logfile. + * It is initialized with the wlog_open() function. This handle is + * then passed to the various wlog_xxx() functions to provide transparent + * access to the write logfile. + * + * The wlog_rec datatype is a structure which contains all the information + * about a file write. Examples include the file name, offset, length, + * pattern, etc. In addition there is a bit which is cleared/set based + * on whether or not the write has been confirmed as complete. This + * allows the write logfile to contain information on writes which have + * been initiated, but not yet completed (as in async io). + * + * There is also a function to scan a write logfile in reverse order. + * + * NOTE: For target file analysis based on a write logfile, the + * assumption is made that the file being written to is + * locked from simultaneous access, so that the order of + * write completion is predictable. This is an issue when + * more than 1 process is trying to write data to the same + * target file simultaneously. + * + * The history file created is a collection of variable length records + * described by scruct wlog_rec_disk in write_log.h. See that module for + * the layout of the data on disk. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "write_log.h" + +#ifndef BSIZE +#ifdef DEV_BSIZE +#define BSIZE DEV_BSIZE +#else +#define BSIZE BBSIZE +#endif +#endif + +#ifndef PATH_MAX +#define PATH_MAX 255 +/*#define PATH_MAX pathconf("/", _PC_PATH_MAX)*/ +#endif + +char Wlog_Error_String[256]; + +#if __STDC__ +static int wlog_rec_pack(struct wlog_rec *wrec, char *buf, int flag); +static int wlog_rec_unpack(struct wlog_rec *wrec, char *buf); +#else +static int wlog_rec_pack(); +static int wlog_rec_unpack(); +#endif + +/* + * Initialize a write logfile. wfile is a wlog_file structure that has + * the w_file field filled in. The rest of the information in the + * structure is initialized by the routine. + * + * The trunc flag is used to indicate whether or not the logfile should + * be truncated if it currently exists. If it is non-zero, the file will + * be truncated, otherwise it will be appended to. + * + * The mode argument is the [absolute] mode which the file will be + * given if it does not exist. This mode is not affected by your process + * umask. + */ + +int +wlog_open(wfile, trunc, mode) +struct wlog_file *wfile; +int trunc; +int mode; +{ + int omask, oflags; + + if (trunc) + trunc = O_TRUNC; + + omask = umask(0); + + /* + * Open 1 file descriptor as O_APPEND + */ + + oflags = O_WRONLY | O_APPEND | O_CREAT | trunc; + wfile->w_afd = + open(wfile->w_file, oflags, mode); + umask(omask); + + if (wfile->w_afd == -1) { + sprintf(Wlog_Error_String, + "Could not open write_log - open(%s, %#o, %#o) failed: %s\n", + wfile->w_file, oflags, mode, strerror(errno)); + return -1; + } + + /* + * Open the next fd as a random access descriptor + */ + + oflags = O_RDWR; + if ((wfile->w_rfd = open(wfile->w_file, oflags)) == -1) { + sprintf(Wlog_Error_String, + "Could not open write log - open(%s, %#o) failed: %s\n", + wfile->w_file, oflags, strerror(errno)); + close(wfile->w_afd); + wfile->w_afd = -1; + return -1; + } + + return 0; +} + +/* + * Release all resources associated with a wlog_file structure allocated + * with the wlog_open() call. + */ + +int +wlog_close(wfile) +struct wlog_file *wfile; +{ + close(wfile->w_afd); + close(wfile->w_rfd); + return 0; +} + +/* + * Write a wlog_rec structure to a write logfile. Offset is used to + * control where the record will be written. If offset is < 0, the + * record will be appended to the end of the logfile. Otherwise, the + * record which exists at the indicated offset will be overlayed. This + * is so that we can record writes which are outstanding (with the w_done + * bit in wrec cleared), but not completed, and then later update the + * logfile when the write request completes (as with async io). When + * offset is >= 0, only the fixed length portion of the record is + * rewritten. See text in write_log.h for details on the format of an + * on-disk record. + * + * The return value of the function is the byte offset in the logfile + * where the record begins. + * + * Note: It is the callers responsibility to make sure that the offset + * parameter 'points' to a valid record location when a record is to be + * overlayed. This is guarenteed by saving the return value of a previous + * call to wlog_record_write() which wrote the record to be overlayed. + * + * Note2: The on-disk version of the wlog_rec is MUCH different than + * the user version. Don't expect to od the logfile and see data formatted + * as it is in the wlog_rec structure. Considerable data packing takes + * place before the record is written. + */ + +int +wlog_record_write(wfile, wrec, offset) +struct wlog_file *wfile; +struct wlog_rec *wrec; +long offset; +{ + int reclen; + char wbuf[WLOG_REC_MAX_SIZE + 2]; + + /* + * If offset is -1, we append the record at the end of file + * + * Otherwise, we overlay wrec at the file offset indicated and assume + * that the caller passed us the correct offset. We do not record the + * fname in this case. + */ + + reclen = wlog_rec_pack(wrec, wbuf, (offset < 0)); + + if (offset < 0) { + /* + * Since we're writing a complete new record, we must also tack + * its length onto the end so that wlog_scan_backward() will work. + * Length is asumed to fit into 2 bytes. + */ + + wbuf[reclen] = reclen / 256; + wbuf[reclen+1] = reclen % 256; + reclen += 2; + + if (write(wfile->w_afd, wbuf, reclen) == -1) { + sprintf(Wlog_Error_String, + "Could not write log - write(%s, %s, %d) failed: %s\n", + wfile->w_file, wbuf, reclen, strerror(errno)); + return -1; + } else { + offset = lseek(wfile->w_afd, 0, SEEK_CUR) - reclen; + if (offset == -1) { + sprintf(Wlog_Error_String, + "Could not reposition file pointer - lseek(%s, 0, SEEK_CUR) failed: %s\n", + wfile->w_file, strerror(errno)); + return -1; + } + } + } else { + if ((lseek(wfile->w_rfd, offset, SEEK_SET)) == -1) { + sprintf(Wlog_Error_String, + "Could not reposition file pointer - lseek(%s, %ld, SEEK_SET) failed: %s\n", + wfile->w_file, offset, strerror(errno)); + return -1; + } else { + if ((write(wfile->w_rfd, wbuf, reclen)) == -1) { + sprintf(Wlog_Error_String, + "Could not write log - write(%s, %s, %d) failed: %s\n", + wfile->w_file, wbuf, reclen, strerror(errno)); + return -1; + } + } + } + + return offset; +} + +/* + * Function to scan a logfile in reverse order. Wfile is a valid + * wlog_file structure initialized by wlog_open(). nrecs is the number + * of records to scan (all records are scanned if nrecs is 0). func is + * a user-supplied function to call for each record found. The function + * will be passed a single parameter - a wlog_rec structure . + */ + +int +wlog_scan_backward(wfile, nrecs, func, data) +struct wlog_file *wfile; +int nrecs; +int (*func)(); +long data; +{ + int fd, leftover, nbytes, offset, recnum, reclen, rval; + char buf[BSIZE*32], *bufend, *cp, *bufstart; + char albuf[WLOG_REC_MAX_SIZE]; + struct wlog_rec wrec; + + fd = wfile->w_rfd; + + /* + * Move to EOF. offset will always hold the current file offset + */ + + if ((lseek(fd, 0, SEEK_END)) == -1) { + sprintf(Wlog_Error_String, + "Could not reposition file pointer - lseek(%s, 0, SEEK_END) failed: %s\n", + wfile->w_file, strerror(errno)); + return -1; + } + offset = lseek(fd, 0, SEEK_CUR); + if ((offset == -1)) { + sprintf(Wlog_Error_String, + "Could not reposition file pointer - lseek(%s, 0, SEEK_CUR) failed: %s\n", + wfile->w_file, strerror(errno)); + return -1; + } + + bufend = buf + sizeof(buf); + bufstart = buf; + + recnum = 0; + leftover = 0; + while ((!nrecs || recnum < nrecs) && offset > 0) { + /* + * Check for beginning of file - if there aren't enough bytes + * remaining to fill buf, adjust bufstart. + */ + + if ((unsigned int)offset + leftover < sizeof(buf)) { + bufstart = bufend - (offset + leftover); + offset = 0; + } else { + offset -= sizeof(buf) - leftover; + } + + /* + * Move to the proper file offset, and read into buf + */ + if ((lseek(fd, offset, SEEK_SET)) ==-1) { + sprintf(Wlog_Error_String, + "Could not reposition file pointer - lseek(%s, %d, SEEK_SET) failed: %s\n", + wfile->w_file, offset, strerror(errno)); + return -1; + } + + nbytes = read(fd, bufstart, bufend - bufstart - leftover); + + if (nbytes == -1) { + sprintf(Wlog_Error_String, + "Could not read history file at offset %d - read(%d, %p, %d) failed: %s\n", + offset, fd, bufstart, + (int)(bufend - bufstart - leftover), strerror(errno)); + return -1; + } + + cp = bufend; + leftover = 0; + + while (cp >= bufstart) { + + /* + * If cp-bufstart is not large enough to hold a piece + * of record length information, copy remainder to end + * of buf and continue reading the file. + */ + + if (cp - bufstart < 2) { + leftover = cp - bufstart; + memcpy(bufend - leftover, bufstart, leftover); + break; + } + + /* + * Extract the record length. We must do it this way + * instead of casting cp to an int because cp might + * not be word aligned. + */ + + reclen = (*(cp-2) * 256) + *(cp -1); + + /* + * If cp-bufstart isn't large enough to hold a + * complete record, plus the length information, copy + * the leftover bytes to the end of buf and continue + * reading. + */ + + if (cp - bufstart < reclen + 2) { + leftover = cp - bufstart; + memcpy(bufend - leftover, bufstart, leftover); + break; + } + + /* + * Adjust cp to point at the start of the record. + * Copy the record into wbuf so that it is word + * aligned and pass the record to the user supplied + * function. + */ + + cp -= reclen + 2; + memcpy(albuf, cp, reclen); + + wlog_rec_unpack(&wrec, albuf); + + /* + * Call the user supplied function - + * stop if instructed to. + */ + + if ((rval = (*func)(&wrec, data)) == WLOG_STOP_SCAN) { + break; + } + + recnum++; + + if (nrecs && recnum >= nrecs) + break; + } + } + + return 0; +} + +/* + * The following 2 routines are used to pack and unpack the user + * visible wlog_rec structure to/from a character buffer which is + * stored or read from the write logfile. Any changes to either of + * these routines must be reflected in the other. + */ + +static int +wlog_rec_pack(wrec, buf, flag) +struct wlog_rec *wrec; +char *buf; +int flag; +{ + char *file, *host, *pattern; + struct wlog_rec_disk *wrecd; + + wrecd = (struct wlog_rec_disk *)buf; + + wrecd->w_pid = (uint)wrec->w_pid; + wrecd->w_offset = (uint)wrec->w_offset; + wrecd->w_nbytes = (uint)wrec->w_nbytes; + wrecd->w_oflags = (uint)wrec->w_oflags; + wrecd->w_done = (uint)wrec->w_done; + wrecd->w_async = (uint)wrec->w_async; + + wrecd->w_pathlen = (wrec->w_pathlen > 0) ? (uint)wrec->w_pathlen : 0; + wrecd->w_hostlen = (wrec->w_hostlen > 0) ? (uint)wrec->w_hostlen : 0; + wrecd->w_patternlen = (wrec->w_patternlen > 0) ? (uint)wrec->w_patternlen : 0; + + /* + * If flag is true, we should also pack the variable length parts + * of the wlog_rec. By default, we only pack the fixed length + * parts. + */ + + if (flag) { + file = buf + sizeof(struct wlog_rec_disk); + host = file + wrecd->w_pathlen; + pattern = host + wrecd->w_hostlen; + + if (wrecd->w_pathlen > 0) + memcpy(file, wrec->w_path, wrecd->w_pathlen); + + if (wrecd->w_hostlen > 0) + memcpy(host, wrec->w_host, wrecd->w_hostlen); + + if (wrecd->w_patternlen > 0) + memcpy(pattern, wrec->w_pattern, wrecd->w_patternlen); + + return (sizeof(struct wlog_rec_disk) + + wrecd->w_pathlen + wrecd->w_hostlen + wrecd->w_patternlen); + } else { + return sizeof(struct wlog_rec_disk); + } +} + +static int +wlog_rec_unpack(wrec, buf) +struct wlog_rec *wrec; +char *buf; +{ + char *file, *host, *pattern; + struct wlog_rec_disk *wrecd; + + memset((char *)wrec, 0x00, sizeof(struct wlog_rec)); + wrecd = (struct wlog_rec_disk *)buf; + + wrec->w_pid = wrecd->w_pid; + wrec->w_offset = wrecd->w_offset; + wrec->w_nbytes = wrecd->w_nbytes; + wrec->w_oflags = wrecd->w_oflags; + wrec->w_hostlen = wrecd->w_hostlen; + wrec->w_pathlen = wrecd->w_pathlen; + wrec->w_patternlen = wrecd->w_patternlen; + wrec->w_done = wrecd->w_done; + wrec->w_async = wrecd->w_async; + + if (wrec->w_pathlen > 0) { + file = buf + sizeof(struct wlog_rec_disk); + memcpy(wrec->w_path, file, wrec->w_pathlen); + } + + if (wrec->w_hostlen > 0) { + host = buf + sizeof(struct wlog_rec_disk) + wrec->w_pathlen; + memcpy(wrec->w_host, host, wrec->w_hostlen); + } + + if (wrec->w_patternlen > 0) { + pattern = buf + sizeof(struct wlog_rec_disk) + + wrec->w_pathlen + wrec->w_hostlen; + memcpy(wrec->w_pattern, pattern, wrec->w_patternlen); + } + + return 0; +} \ No newline at end of file diff --git a/ltp_framework/runltp b/ltp_framework/runltp new file mode 100755 index 0000000..65aea44 --- /dev/null +++ b/ltp_framework/runltp @@ -0,0 +1,1005 @@ +#!/bin/sh +################################################################################ +## ## +## Copyright (c) International Business Machines Corp., 2001 ## +## ## +## This program is free software; you can redistribute it and#or modify ## +## it under the terms of the GNU General Public License as published by ## +## the Free Software Foundation; either version 2 of the License, or ## +## (at your option) any later version. ## +## ## +## This program is distributed in the hope that it will be useful, but ## +## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ## +## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ## +## for more details. ## +## ## +## You should have received a copy of the GNU General Public License ## +## along with this program; if not, write to the Free Software ## +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## +## ## +################################################################################ +# File: runltp +# +# Description: This script can be used to the tests in the LTP test suite +# +# Authors: Manoj Iyer - manjo@mail.utexas.edu +# Robbe Williamson - robbiew@us.ibm.com +# +# History: Oct 07 2003 - Modified - Manoj Iyer +# - use functions +# - clean up on script exit +# - error checking etc. +# +# Oct 08 2003 - Modified - Manoj Iyer +# - fixed bug in creating results directory +# - all checks should be enlclosed in " " to avoid bash error +# - exit with error if ltp-pan is not found in pan directory +# +# Jul 22 2007 - Modified - Ricardo Salveti de Araujo +# - added support to put more then one file at CMDLINE (-f) +# - added a new option, that the user can pass the address of +# the command file, and it'll use wget to get it (-w) +# - now -s does the grep at the selected command files (default, +# -f or -w) +# +# Jul 23 2007 - Modified - Ricardo Salveti de Araujo +# - added flag to get the command file that has all failed tests +# +# Sep 11 2007 - Modified - Subrata Modak +# - added option to create Failed File if it is not an absolute path +# - added option to create Output File if it is not an absolute path +# - added option to create Failed File compulsory, even if user has not mentioned it +# +# Sep 14 2007 - Modified - Ricardo Salveti de Araujo +# - cleaning and removing duplicated code +# +# Oct 27 2007 - Modified - Ricardo Salveti de Araujo and Subrata Modak +# - better ways to integrate "ltp/tools/genload/stress" with "ltp/runltp" +# Nov 24 2007 - Modified - Subrata Modak +# - Added a new option to generate output in HTML format also. Also retaining +# the original test format +# Nov 28 2007 - Modified - Subrata Modak +# - Added a new option to mail back LTP reports +# May 19 2008 - Modified - Subrata Modak +# - Added capability for default Log file generation +# Aug 17 2009 - Modified - Subrata Modak +# - Added Fault Injection generation Capability through -F Option +# +################################################################################# + + + +setup() +{ + sync + echo 3 > /proc/sys/vm/drop_caches + sync + echo 3 > /proc/sys/vm/drop_caches + sync + echo 3 > /proc/sys/vm/drop_caches + + cd `dirname $0` || \ + { + echo "FATAL: unable to change directory to $(dirname $0)" + exit 1 + } + export LTPROOT=${PWD} + export TMPBASE="/tmp" + export PATH="${PATH}:${LTPROOT}/testcases/bin" + export BOARD=u8500 + export MMC_MOUNTPOINT=/mnt/sdcard + export ONBOARD_EMMC_MOUNTPOINT=/mnt/onboardemmc + export ONBOARD_EMMC_NODE=/dev/mmcblk1p1 + + # various things required for some tests + mkdir -p /tmp /opt /proc /sys /proc /dev + mount -t proc proc /proc 2>/dev/null + mount -t sysfs nodev /sys 2>/dev/null + + ln -s /dev /dev/misc 2>/dev/null + mdev -s 2>/dev/null + echo `which mdev` > /proc/sys/kernel/hotplug + + touch /etc/hosts + [ -f /etc/hostid ] || echo 123 > /etc/hostid + mkdir -p /dev/shm && mount -t tmpfs nodev /dev/shm 2>/dev/null + ifconfig lo up + + + [ -d "$LTPROOT/testcases/bin" ] || + { + echo "FATAL: LTP not installed correctly" + echo "INFO: Follow directions in INSTALL!" + exit 1 + } + + [ -e "$LTPROOT/bin/ltp-pan" ] || + { + echo "FATAL: Test suite driver 'ltp-pan' not found" + echo "INFO: Follow directions in INSTALL!" + exit 1 + } +} + +version_of_ltp() +{ + cat "$LTPROOT/Version" + exit 0 +} + +usage() +{ + cat <<-EOF >&2 + + usage: ${0##*/} [ -a EMAIL_TO ] [ -c NUM_PROCS ] [ -C FAILCMDFILE ] [ -d TMPDIR ] + [ -D NUM_PROCS,NUM_FILES,NUM_BYTES,CLEAN_FLAG ] -e [ -f CMDFILES(,...) ] [ -g HTMLFILE] + [ -i NUM_PROCS ] [ -l LOGFILE ] [ -m NUM_PROCS,CHUNKS,BYTES,HANGUP_FLAG ] + -N -n [ -o OUTPUTFILE ] -p -q [ -r LTPROOT ] [ -s PATTERN ] [ -t DURATION ] + -v [ -w CMDFILEADDR ] [ -x INSTANCES ] [ -b DEVICE ] [-B DEVICE_FS_TYPE] + [ -F LOOPS,PERCENTAGE ] + + -a EMAIL_TO EMAIL all your Reports to this E-mail Address + -c NUM_PROCS Run LTP under additional background CPU load + [NUM_PROCS = no. of processes creating the CPU Load by spinning over sqrt() + (Defaults to 1 when value)] + -C FAILCMDFILE Command file with all failed test cases. + -d TMPDIR Directory where temporary files will be created. + -D NUM_PROCS,NUM_FILES,NUM_BYTES,CLEAN_FLAG + Run LTP under additional background Load on Secondary Storage (Seperate by comma) + [NUM_PROCS = no. of processes creating Storage Load by spinning over write()] + [NUM_FILES = Write() to these many files (Defaults to 1 when value 0 or undefined)] + [NUM_BYTES = write these many bytes (defaults to 1GB, when value 0 or undefined)] + [CLEAN_FLAG = unlink file to which random data written, when value 1] + -e Prints the date of the current LTP release + -f CMDFILES Execute user defined list of testcases (separate with ',') + -F LOOPS,PERCENTAGE Induce PERCENTAGE Fault in the Kernel Subsystems, and, run each test for LOOPS loop + -g HTMLFILE Create an additional HTML output format + -h Help. Prints all available options. + -i NUM_PROCS Run LTP under additional background Load on IO Bus + [NUM_PROCS = no. of processes creating IO Bus Load by spinning over sync()] + -K DMESG_LOG_DIR + Log Kernel messages generated for each test cases inside this directory + -l LOGFILE Log results of test in a logfile. + -m NUM_PROCS,CHUNKS,BYTES,HANGUP_FLAG + Run LTP under additional background Load on Main memory (Seperate by comma) + [NUM_PROCS = no. of processes creating main Memory Load by spinning over malloc()] + [CHUNKS = malloc these many chunks (default is 1 when value 0 or undefined)] + [BYTES = malloc CHUNKS of BYTES bytes (default is 256MB when value 0 or undefined) ] + [HANGUP_FLAG = hang in a sleep loop after memory allocated, when value 1] + -M CHECK_TYPE + [CHECK_TYPE=1 => Full Memory Leak Check tracing children as well] + [CHECK_TYPE=2 => Thread Concurrency Check tracing children as well] + [CHECK_TYPE=3 => Full Memory Leak & Thread Concurrency Check tracing children as well] + -N Run all the networking tests. + -n Run LTP with network traffic in background. + -o OUTPUTFILE Redirect test output to a file. + -p Human readable format logfiles. + -q Print less verbose output to screen. + -r LTPROOT Fully qualified path where testsuite is installed. + -s PATTERN Only run test cases which match PATTERN. + -S SKIPFILE Skip tests specified in SKIPFILE + -t DURATION Execute the testsuite for given duration. Examples: + -t 60s = 60 seconds + -t 45m = 45 minutes + -t 24h = 24 hours + -t 2d = 2 days + -T REPETITION Execute the testsuite for REPETITION no. of times + -w CMDFILEADDR Uses wget to get the user's list of testcases. + -x INSTANCES Run multiple instances of this testsuite. + -b DEVICE Some tests require an unmounted block device + to run correctly. + -B DEVICE_FS_TYPE The file system of test block devices. + + + example: ${0##*/} -c 2 -i 2 -m 2,4,10240,1 -D 2,10,10240,1 -p -q -l /tmp/result-log.$$ -o /tmp/result-output.$$ -C /tmp/result-failed.$$ -d ${PWD} + + + EOF +exit 0 +} + +main() +{ + local CMDFILES="" + local PRETTY_PRT="" + local ALT_DIR_OUT=0 + local ALT_DIR_RES=0 + local ALT_HTML_OUT=0 + local ALT_EMAIL_OUT=0 + local ALT_DMESG_OUT=0 + local RUN_NETEST=0 + local RUN_REPEATED=0 + local QUIET_MODE="" + local NETPIPE=0 + local GENLOAD=0 + local MEMSIZE=0 + local DURATION="" + local CMDFILEADDR="" + local FAILCMDFILE="" + local INJECT_KERNEL_FAULT="" + local INJECT_KERNEL_FAULT_PERCENTAGE="" + local INJECT_FAULT_LOOPS_PER_TEST="" + local VALGRIND_CHECK="" + local VALGRIND_CHECK_TYPE="" + local LOGFILE_NAME="" + local LOGFILE="" + local OUTPUTFILE_NAME="" + local OUTPUTFILE="" + local HTMLFILE_NAME="" + local HTMLFILE="" + local DMESG_DIR="" + local EMAIL_TO="" + local TAG_RESTRICT_STRING="" + local PAN_COMMAND="" + local DEFAULT_FILE_NAME_GENERATION_TIME=`date +"%Y_%b_%d-%Hh_%Mm_%Ss"` + + local scenfile= + + version_date=`head -n 1 $LTPROOT/ChangeLog` + kernel_version=`uname -r` + + while getopts a:c:C:d:D:f:F:ehi:K:g:l:m:M:Nno:pqr:s:S:t:T:w:x:b:B: arg + do case $arg in + a) EMAIL_TO=$OPTARG + ALT_EMAIL_OUT=1;; + c) + NUM_PROCS=$(($OPTARG)) + if [ "$NUM_PROCS" -eq 0 ]; then + # User Did not Define the Value ,or, User Defined Zero, + # hence, prevent from creating infinite processes + NUM_PROCS=1 + fi + $LTPROOT/testcases/bin/genload --cpu $NUM_PROCS >/dev/null 2>&1 & + GENLOAD=1 ;; + + C) + case $OPTARG in + /*) + FAILCMDFILE="-C $OPTARG" ;; + *) + FAILCMDFILE="-C $LTPROOT/output/$OPTARG" + ALT_DIR_OUT=1 ;; + esac ;; + + d) # convert the user path to absolute path. + export TMPBASE=`cd \`dirname ${OPTARG}\`; pwd`/`basename ${OPTARG}` ;; + + D) NUM_PROCS=1; NUM_FILES=1; NUM_BYTES=$((1024 * 1024 * 1024)); CLEAN_FLAG=0 + ARGUMENT_LIST=$OPTARG + TOTAL_ARGUMENTS=1 + for ARGUMENT in `echo "$ARGUMENT_LIST" | tr ',' ' '` + do + case $TOTAL_ARGUMENTS in + 1) NUM_PROCS="$ARGUMENT" ;; + 2) NUM_FILES="$ARGUMENT" ;; + 3) NUM_BYTES="$ARGUMENT" ;; + 4) CLEAN_FLAG="$ARGUMENT" ;; + esac + TOTAL_ARGUMENTS=`expr $TOTAL_ARGUMENTS + 1` + done + # just to get the default values if the user passed 0 + if [ "$NUM_PROCS" -eq 0 ]; then + NUM_PROCS=1 + fi + if [ "$NUM_FILES" -eq 0 ]; then + NUM_FILES=1 + fi + if [ "$NUM_BYTES" -eq 0 ]; then + NUM_BYTES=$((1024 * 1024 * 1024)) + fi + if [ "$CLEAN_FLAG" -ne 1 ]; then + CLEAN_FLAG=0 + fi + if [ "$CLEAN_FLAG" -eq 1 ]; then + # Do not unlink file in this case + $LTPROOT/testcases/bin/genload --hdd $NUM_PROCS --hdd-files \ + $NUM_FILES --hdd-bytes $NUM_BYTES >/dev/null 2>&1 & + else + # Cleanup otherwise + $LTPROOT/testcases/bin/genload --hdd $NUM_PROCS --hdd-files \ + $NUM_FILES --hdd-bytes $NUM_BYTES --hdd-noclean >/dev/null 2>&1 & + fi + GENLOAD=1;; + + e) # Print out the version of LTP + version_of_ltp + ;; + f) # Execute user defined set of testcases. + # Can be more then one file, just separate it with ',', like: + # -f nfs,commands,/tmp/testfile + CMDFILES=$OPTARG;; + F) INJECT_KERNEL_FAULT=1 + #Seperate out the NO_OF_LOOPS & FAULT_PERCENTAGE + INJECT_FAULT_LOOPS_PER_TEST=`echo $OPTARG |cut -d',' -f1 | tr -d '\n' | tr -d ' '` + INJECT_KERNEL_FAULT_PERCENTAGE=`echo $OPTARG |cut -d',' -f2 | tr -d '\n' | tr -d ' '` + if [ ! $INJECT_FAULT_LOOPS_PER_TEST ]; then + echo "Loops not properly defined. Resorting to default 5..." + export INJECT_FAULT_LOOPS_PER_TEST=5 + fi + if [ ! $INJECT_KERNEL_FAULT_PERCENTAGE ]; then + echo "Fault Persentage not properly defined. Resorting to default 10..." + export INJECT_KERNEL_FAULT_PERCENTAGE=10 + fi;; + g) HTMLFILE_NAME="$OPTARG" + case $OPTARG in + /*) + HTMLFILE="$OPTARG";; + *) + HTMLFILE="$LTPROOT/output/$OPTARG";; + esac + ALT_DIR_OUT=1 + ALT_HTML_OUT=1;; + h) usage;; + + i) + NUM_PROCS=$(($OPTARG)) + if [ "$NUM_PROCS" -eq 0 ]; then + # User Did not Define the Value ,or, User Defined Zero, + # hence, prevent from creating infinite processes + NUM_PROCS=1 + fi + $LTPROOT/testcases/bin/genload --io $NUM_PROCS >/dev/null 2>&1 & + GENLOAD=1 ;; + + K) + case $OPTARG in + /*) + DMESG_DIR="$OPTARG-dmesg-output-`echo $$-``date +%X | tr -d ' '`";; + *) + DMESG_DIR="$LTPROOT/output/$OPTARG-dmesg-output-`echo $$-``date +%X | tr -d ' '`";; + esac + mkdir -p $DMESG_DIR + ALT_DMESG_OUT=1;; + l) + LOGFILE_NAME="$OPTARG" + case $OPTARG in + /*) + LOGFILE="-l $OPTARG" ;; + *) + LOGFILE="-l $LTPROOT/results/$OPTARG" + ALT_DIR_RES=1 ;; + esac ;; + + m) NUM_PROCS=1; CHUNKS=1; BYTES=$((256 * 1024 * 1024)); HANGUP_FLAG=0 + ARGUMENT_LIST=$OPTARG + TOTAL_ARGUMENTS=1 + for ARGUMENT in `echo "$ARGUMENT_LIST" | tr ',' ' '` + do + case $TOTAL_ARGUMENTS in + 1) NUM_PROCS="$ARGUMENT" ;; + 2) CHUNKS="$ARGUMENT" ;; + 3) BYTES="$ARGUMENT" ;; + 4) HANGUP_FLAG="$ARGUMENT" ;; + esac + TOTAL_ARGUMENTS=`expr $TOTAL_ARGUMENTS + 1` + done + # just to get the default values if the user passed 0 + if [ "$NUM_PROCS" -eq 0 ]; then + NUM_PROCS=1 + fi + if [ "$CHUNKS" -eq 0 ]; then + CHUNKS=1 + fi + if [ "$BYTES" -eq 0 ]; then + BYTES=$((256 * 1024 * 1024)) + fi + if [ "$HANGUP_FLAG" -ne 1 ]; then + HANGUP_FLAG=0 + fi + if [ "$HANGUP_FLAG" -eq 1 ]; then + # Hang in a Sleep loop after memory allocated + $LTPROOT/testcases/bin/genload --vm $NUM_PROCS --vm-chunks \ + $CHUNKS --vm-bytes $BYTES --vm-hang >/dev/null 2>&1 & + else + # Otherwise Do not Hangup + $LTPROOT/testcases/bin/genload --vm $NUM_PROCS --vm-chunks \ + $CHUNKS --vm-bytes $BYTES >/dev/null 2>&1 & + fi + GENLOAD=1;; + M) + VALGRIND_CHECK=1 + VALGRIND_CHECK_TYPE="$OPTARG";; + + N) RUN_NETEST=1;; + + n) + $LTPROOT/testcases/bin/netpipe.sh + NETPIPE=1;; + + o) OUTPUTFILE_NAME="$OPTARG" + case $OPTARG in + /*) + OUTPUTFILE="-o $OPTARG";; + *) + OUTPUTFILE="-o $LTPROOT/output/$OPTARG" + ALT_DIR_OUT=1 ;; + esac ;; + + p) PRETTY_PRT=" -p ";; + + q) QUIET_MODE=" -q ";; + + r) LTPROOT=$OPTARG;; + + s) TAG_RESTRICT_STRING=$OPTARG;; + + S) case $OPTARG in + /*) + SKIPFILE=$OPTARG;; + *) + SKIPFILE="$LTPROOT/$OPTARG";; + esac ;; + + t) # In case you want to specify the time + # to run from the command line + # (2m = two minutes, 2h = two hours, etc) + DURATION="-t $OPTARG" ;; + + T) # In case you want the testcases to runsequentially RUN_REPEATED times + RUN_REPEATED=$OPTARG;; + + w) CMDFILEADDR=$OPTARG;; + + x) # number of ltp's to run + cat <<-EOF >&1 + WARNING: The use of -x can cause unpredictable failures, as a + result of concurrently running multiple tests designed + to be ran exclusively. + Pausing for 10 seconds..." + EOF + sleep 10 + INSTANCES="-x $OPTARG";; + b) DEVICE=$OPTARG;; + B) DEVICE_FS_TYPE=$OPTARG;; + \?) usage;; + esac + done + + ## It would be nice to create a default log file even if the user has not mentioned + if [ ! "$LOGFILE" ]; then ## User has not mentioned about Log File name + LOGFILE_NAME=$DEFAULT_FILE_NAME_GENERATION_TIME + LOGFILE="-l $LTPROOT/results/LTP_RUN_ON-$LOGFILE_NAME.log" + ALT_DIR_RES=1 + PRETTY_PRT=" -p " + fi + + ## It would be nice if a Failed File is compulsorily created (gives User better Idea of Tests that failed) + + if [ ! "$FAILCMDFILE" ]; then ## User has not mentioned about Failed File name + ALT_DIR_OUT=1 + if [ ! "$OUTPUTFILE" ]; then ## User has not mentioned about Output File name either + if [ ! "$LOGFILE" ]; then ## User has not mentioned about Log File name either + FAILED_FILE_NAME=$DEFAULT_FILE_NAME_GENERATION_TIME + FAILCMDFILE="-C $LTPROOT/output/LTP_RUN_ON-$FAILED_FILE_NAME.failed" + else ## User Fortunately wanted a log file, + FAILED_FILE_NAME=`basename $LOGFILE_NAME` ## Extract log file name and use it to construct Failed file name + FAILCMDFILE="-C $LTPROOT/output/LTP_RUN_ON-$FAILED_FILE_NAME.failed" + fi + else ## User Fortunately wanted a Output file + FAILED_FILE_NAME=`basename $OUTPUTFILE_NAME` ## Extract output file name and use it to construct Failed file name + FAILCMDFILE="-C $LTPROOT/output/LTP_RUN_ON-$FAILED_FILE_NAME.failed" + fi + fi + + if [ "$ALT_HTML_OUT" -eq 1 ] ; then ## User wants the HTML version of the output + QUIET_MODE="" ## Suppressing this guy as it will prevent generation of proper output + ## which the HTML parser will require + if [ ! "$OUTPUTFILE" ]; then ## User has not mentioned about the Outputfile name, then we need to definitely generate one + OUTPUTFILE_NAME=$DEFAULT_FILE_NAME_GENERATION_TIME + OUTPUTFILE="-o $LTPROOT/output/LTP_RUN_ON-$OUTPUTFILE_NAME.output" + ALT_DIR_OUT=1 + if [ ! "$HTMLFILE" ] ; then ## User has not mentioned HTML File name, We need to create one + HTMLFILE_NAME=`basename $OUTPUTFILE_NAME` + HTMLFILE="$LTPROOT/output/$HTMLFILE_NAME.html" + fi + fi + fi + + # If we need, create the output directory + [ "$ALT_DIR_OUT" -eq 1 ] && \ + { + [ ! -d $LTPROOT/output ] && \ + { + echo "INFO: creating $LTPROOT/output directory" + mkdir -p $LTPROOT/output || \ + { + echo "ERROR: failed to create $LTPROOT/output" + exit 1 + } + } + } + # If we need, create the results directory + [ "$ALT_DIR_RES" -eq 1 ] && \ + { + echo "INFO: creating $LTPROOT/results directory" + [ ! -d $LTPROOT/results ] && \ + { + mkdir -p $LTPROOT/results || \ + { + echo "ERROR: failed to create $LTPROOT/results" + exit 1 + } + } + } + + # Added -m 777 for tests that call tst_tmpdir() and try to + # write to it as user nobody + mkdir -m 777 -p $TMPBASE || \ + { + echo "FATAL: Unable to make temporary directory $TMPBASE" + exit 1 + } + # use mktemp to create "safe" temporary directories + export TMPTEMPLATE="${TMPBASE}/ltp-XXXXXXXXXX" + TMP=`mktemp -d $TMPTEMPLATE` || \ + { + echo "FATAL: Unable to make temporary directory: $TMP" + exit 1 + } + export TMP + # To be invoked by tst_tmpdir() + # write to it as user nobody + export TMPDIR=$TMP + + chmod 777 $TMP || \ + { + echo "unable to chmod 777 $TMP ... aborting" + exit 1 + } + + cd $TMP || \ + { + echo "could not cd ${TMP} ... exiting" + exit 1 + } + + [ -n "$INSTANCES" ] && \ + { + INSTANCES="$INSTANCES -O ${TMP}" + } + + [ "$RUN_NETEST" -eq 1 ] && \ + { + [ -z "$RHOST" ] || [ -z "$PASSWD" ] && \ + { + [ -z "$RHOST" ] && \ + { + echo \ + "INFO: Enter RHOST = 'name of the remote host machine'" + echo -n "-> " + read RHOST + } + + [ -z "$PASSWD" ] && \ + { + echo " " + echo \ + "INFO: Enter PASSWD = 'root passwd of the remote host machine'" + echo -n "-> " + read PASSWD + } + export RHOST=$RHOST + export PASSWD=$PASSWD + echo "WARNING: security of $RHOST may be compromised" + } + } + + # If user does not provide a command file select a default set of testcases + # to execute. + if [ -z "$CMDFILES" ] && [ -z "$CMDFILEADDR" ] + then + cat <<-EOF >&1 + + INFO: no command files were provided. Will execute the following + runtest scenario files: + +`cat $LTPROOT/scenario_groups/default | tr '\012' ' '` + + EOF + + SCENARIO_LISTS="$LTPROOT/scenario_groups/default" + if [ "$RUN_NETEST" -eq 1 ]; then + SCENARIO_LISTS="$SCENARIO_LISTS $LTPROOT/scenario_groups/network" + fi + + # DO NOT INDENT/DEDENT! + if [ -n "$SCENARIO_LISTS" ]; then + # Insurance to make sure that the first element in the pipe + # completed successfully. + cat_ok_sentinel=$TMP/cat_ok.$$ + (cat $SCENARIO_LISTS && touch "$cat_ok_sentinel") | \ + while read scenfile; do + + scenfile=${LTPROOT}/runtest/$scenfile + + # Skip over non-existent scenario files; things are + # robust enough now that the build will fail if these + # files don't exist. + [ -f "$scenfile" ] || continue + + cat $scenfile >> "$TMP/alltests" || { + echo "FATAL: unable to append to command file" + rm -Rf "$TMP" + rm -f "$cat_ok_sentinel" + exit 1 + } + + done + + rm -f "$cat_ok_sentinel" + + fi + # ^^DO NOT INDENT/DEDENT!^^ + + fi + + [ -n "$CMDFILES" ] && \ + { + for scenfile in `echo "$CMDFILES" | tr ',' ' '` + do + [ -f "$scenfile" ] || scenfile="$LTPROOT/runtest/$scenfile" + cat "$scenfile" >> ${TMP}/alltests || \ + { + echo "FATAL: unable to create command file" + rm -Rf "$TMP" + exit 1 + } + done + } + + [ -n "$CMDFILEADDR" ] && \ + { + wget -q "${CMDFILEADDR}" -O ${TMP}/wgetcmdfile + if [ $? -ne 0 ]; then + echo "FATAL: error while getting the command file with wget (address $CMDFILEADDR)" + exit 1 + fi + cat "${TMP}/wgetcmdfile" >> ${TMP}/alltests || \ + { + echo "FATAL: unable to create command file" + exit 1 + } + } + + # The fsx-linux tests use the SCRATCHDEV environment variable as a location + # that can be reformatted and run on. Set SCRATCHDEV if you want to run + # these tests. As a safeguard, this is disabled. + unset SCRATCHDEV + [ -n "$SCRATCHDEV" ] && \ + { + cat ${LTPROOT}/runtest/fsx >> ${TMP}/alltests || + { + echo "FATAL: unable to create fsx-linux tests command file" + exit 1 + } + } + + # If enabled, execute only test cases that match the PATTERN + if [ -n "$TAG_RESTRICT_STRING" ] + then + mv -f ${TMP}/alltests ${TMP}/alltests.orig + grep $TAG_RESTRICT_STRING ${TMP}/alltests.orig > ${TMP}/alltests #Not worth checking return codes for this case + fi + + # Blacklist or skip tests if a SKIPFILE was specified with -S + if [ -n "$SKIPFILE" ] + then + for file in $( cat $SKIPFILE ); do + sed -i "/^$file[ \t]/d" ${TMP}/alltests + done + fi + + # check for required users and groups + ${LTPROOT}/IDcheck.sh &>/dev/null || \ + { + echo "WARNING: required users and groups not present" + echo "WARNING: some test cases may fail" + } + + # display versions of installed software + [ -z "$QUIET_MODE" ] && \ + { + ${LTPROOT}/ver_linux || \ + { + echo "WARNING: unable to display versions of software installed" + exit 1 + } + } + + if [ -n "$DEVICE" ]; then + sed -i "s|DEVICE|$DEVICE|" ${TMP}/alltests + else + echo "remove test cases which require the block device." + echo "You can specify it with option -b" + sed -i "/DEVICE/d" ${TMP}/alltests + fi + + if [ $? -ne 0 ]; then + echo "FATAL: error during prcessing alltests file by sed" + exit 1 + fi + + if [ -n "$DEVICE" ]; then + mnt_pnt=`mktemp -d --tmpdir=${TMP} mnt_pnt.XXXXXX` + if [ -n "$DEVICE_FS_TYPE" ]; then + mount -t $DEVICE_FS_TYPE $DEVICE $mnt_pnt + else + mount $DEVICE $mnt_pnt + fi + + if [ $? -ne 0 ]; then + echo "FATAL: can't mount block device $DEVICE." + exit 1 + fi + + if [ -z "$DEVICE_FS_TYPE" ]; then + DEVICE_FS_TYPE=`cat /proc/mounts | awk "{if (\\\$1 == \"$DEVICE\") print \\\$3; }"` + echo "determine file system $DEVICE_FS_TYPE on block device $DEVICE" + fi + + umount $DEVICE + if [ $? -ne 0 ]; then + echo "FATAL: can't umount $DEVICE" + exit 1 + fi + rm -rf $mnt_pnt + fi + + if [ -n "$DEVICE" ]; then + sed -i "" -e "s|DEVICE_FS_TYPE|$DEVICE_FS_TYPE|" ${TMP}/alltests + fi + + if [ $? -ne 0 ]; then + echo "FATAL: error during processing alltests file by sed" + exit 1 + fi + + if [ $RUN_REPEATED -gt 1 ]; then # You need to specify at least more than 1 sequential run, else it runs default + echo "PAN will run these test cases $RUN_REPEATED times....." + echo "Test Tags will be Prepended with ITERATION NO.s....." + inc=1 + sed -e '/^$/ d' -e 's/^[ ,\t]*//' -e '/^#/ d' < ${TMP}/alltests > ${TMP}/alltests.temp ##This removes all newlines, leading spaces, tabs, # + sed 's/^[0-9,a-z,A-Z]*/'"$inc"'_ITERATION_&/' < ${TMP}/alltests.temp > ${TMP}/alltests ## .temp is kept as Base file + while [ $inc -lt $RUN_REPEATED ] ; do + inc=`expr $inc + 1` + sed 's/^[0-9,a-z,A-Z]*/'"$inc"'_ITERATION_&/' < ${TMP}/alltests.temp >> ${TMP}/alltests #Keep appending with Iteration No.s + done + fi + + [ ! -z "$QUIET_MODE" ] && { echo "INFO: Test start time: $(date)" ; } + PAN_COMMAND="${LTPROOT}/bin/ltp-pan $QUIET_MODE -e -S $INSTANCES $DURATION -a $$ \ + -n $$ $PRETTY_PRT -f ${TMP}/alltests $LOGFILE $OUTPUTFILE $FAILCMDFILE" + echo "COMMAND: $PAN_COMMAND" + if [ ! -z "$TAG_RESTRICT_STRING" ] ; then + echo "INFO: Restricted to $TAG_RESTRICT_STRING" + fi + #$PAN_COMMAND #Duplicated code here, because otherwise if we fail, only "PAN_COMMAND" gets output + + ## Display the Output/Log/Failed/HTML file names here + echo -e "LOG File: \c" + echo $LOGFILE | cut -b4- + + if [ "$OUTPUTFILE" ]; then + echo -e "OUTPUT File: \c" + echo $OUTPUTFILE | cut -b4- + fi + + echo -e "FAILED COMMAND File: \c" + echo $FAILCMDFILE | cut -b4- + + if [ "$HTMLFILE" ]; then + echo "HTML File: $HTMLFILE" + fi + + echo "Running tests......." + test_start_time=$(date) + + # User wants testing with Kernel Fault Injection + if [ $INJECT_KERNEL_FAULT ] ; then + #See if Debugfs is mounted, and + #Fault Injection Framework available through Debugfs + if [ -d "/sys/kernel/debug/fail_io_timeout" -o \ + -d "/sys/kernel/debug/fail_make_request" -o \ + -d "/sys/kernel/debug/fail_page_alloc" -o \ + -d "/sys/kernel/debug/failslab" ]; then + #If atleast one of the Framework is available + #Go ahead to Inject Fault & Create required + #Command Files for LTP run + echo Running tests with Fault Injection Enabled in the Kernel... + ${LTPROOT}/bin/create_kernel_faults_in_loops_and_probability.pl\ + ${TMP}/alltests $INJECT_FAULT_LOOPS_PER_TEST $INJECT_KERNEL_FAULT_PERCENTAGE > ${TMP}/alltests.tmp + cp ${TMP}/alltests.tmp ${TMP}/alltests + rm -rf ${TMP}/alltests.tmp + else + echo Fault Injection not enabled in the Kernel.. + echo Running tests normally... + fi + fi + + ## Valgrind Check will work only when Kernel Fault Injection is not expected, + ## We do not want to test Faults when valgrind is running + if [ $VALGRIND_CHECK ]; then + if [ ! $INJECT_KERNEL_FAULT ]; then + which valgrind || VALGRIND_CHECK_TYPE=XYZ + case $VALGRIND_CHECK_TYPE in + 1) + ${LTPROOT}/bin/create_valgrind_check.pl ${TMP}/alltests 1 > ${TMP}/alltests.tmp + cp ${TMP}/alltests.tmp ${TMP}/alltests + rm -rf ${TMP}/alltests.tmp;; + 2) + ${LTPROOT}/bin/create_valgrind_check.pl ${TMP}/alltests 2 > ${TMP}/alltests.tmp + cp ${TMP}/alltests.tmp ${TMP}/alltests + rm -rf ${TMP}/alltests.tmp;; + 3) + ${LTPROOT}/bin/create_valgrind_check.pl ${TMP}/alltests 3 > ${TMP}/alltests.tmp + cp ${TMP}/alltests.tmp ${TMP}/alltests + rm -rf ${TMP}/alltests.tmp;; + *) echo "Invalid Memory Check Type, or, Valgrind is not available";; + esac + fi + fi + + if [ $ALT_DMESG_OUT -eq 1 ] ; then + #We want to print dmesg output for each test,lets do the trick inside the script + echo Enabling dmesg output logging for each test... + ${LTPROOT}/bin/create_dmesg_entries_for_each_test.pl ${TMP}/alltests $DMESG_DIR > ${TMP}/alltests.tmp + cp ${TMP}/alltests.tmp ${TMP}/alltests + rm -rf ${TMP}/alltests.tmp + fi + # Some tests need to run inside the "bin" directory. + cd "${LTPROOT}/testcases/bin" + "${LTPROOT}/bin/ltp-pan" $QUIET_MODE -e -S $INSTANCES $DURATION -a $$ -n $$ $PRETTY_PRT -f ${TMP}/alltests $LOGFILE $OUTPUTFILE $FAILCMDFILE + + if [ $? -eq 0 ]; then + echo "INFO: ltp-pan reported all tests PASS" + VALUE=0 + export LTP_EXIT_VALUE=0; + else + echo "INFO: ltp-pan reported some tests FAIL" + VALUE=1 + export LTP_EXIT_VALUE=1; + fi + cd .. + echo "LTP Version: $version_date" + + if [ $OUTPUTFILE_NAME ]; then + cd "${LTPROOT}/output" + echo "Kernel Version: $kernel_version" >> $OUTPUTFILE_NAME + echo "LTP Version: $version_date" >> $OUTPUTFILE_NAME + cd .. + fi + + # $DMESG_DIR is used to cache messages obtained from dmesg after a test run. + # Proactively reap all of the 0-byte files in $DMESG_DIR as they have zero value + # and only clutter up the filesystem. + + if [ $ALT_DMESG_OUT -eq 1 ] ; then + if ! find "$DMESG_DIR" -size 0 -exec rm {} + ; then + echo "cd to $DMESG_DIR failed: $?" + fi + if [ -n "$(ls "$DMESG_DIR")" ] ; then + echo "Kernel messages were generated for LTP tests $version_date" + else + echo "No Kernel messages were generated for LTP tests $version_date" + fi + fi + + if [ "$ALT_HTML_OUT" -eq 1 ] ; then #User wants the HTML output to be created, it then needs to be generated + export LTP_VERSION=$version_date + export TEST_START_TIME=$test_start_time + export TEST_END_TIME=$(date) + OUTPUT_DIRECTORY=`echo $OUTPUTFILE | cut -c4-` + LOGS_DIRECTORY="$LTPROOT/results" + export TEST_OUTPUT_DIRECTORY="$LTPROOT/output" + export TEST_LOGS_DIRECTORY=$LOGS_DIRECTORY + echo "Generating HTML Output.....!!" + ( perl $LTPROOT/bin/genhtml.pl $LTPROOT/bin/html_report_header.txt test_start test_end test_output execution_status $OUTPUT_DIRECTORY > $HTMLFILE; ) + echo "Generated HTML Output.....!!" + echo "Location: $HTMLFILE"; + + fi + + if [ "$ALT_EMAIL_OUT" -eq 1 ] ; then ## User wants reports to be e-mailed + if [ [ ! "$HTMLFILE_NAME" ] -o [ ! "$OUTPUTFILE_NAME" ] -o [ ! "$LOGFILE_NAME" ] ] ; then + ##User does not have output/logs/html-output, nothing to be mailed in this situation + echo "Nothing to be mailed here...." + else + TAR_FILE_NAME=LTP_RUN_$version_date$DEFAULT_FILE_NAME_GENERATION_TIME.tar + if [ "$HTMLFILE_NAME" ] ; then ## HTML file Exists + if [ "$ALT_HTML_OUT" -ne 1 ] ; then ## The HTML file path is absolute and not $LTPROOT/output + mkdir -p $LTPROOT/output ## We need to create this Directory + cp $HTMLFILE_NAME $LTPROOT/output/ + fi + fi + if [ "$OUTPUTFILE_NAME" ] ; then ## Output file exists + if [ "$ALT_DIR_OUT" -ne 1 ] ; then ## The Output file path is absolute and not $LTPROOT/output + mkdir -p $LTPROOT/output ## We need to create this Directory + cp $OUTPUTFILE_NAME $LTPROOT/output/ + fi + fi + if [ "$LOGFILE_NAME" ] ; then ## Log file exists + if [ "$ALT_DIR_RES" -ne 1 ] ; then ## The Log file path is absolute and not $LTPROOT/results + mkdir -p $LTPROOT/results ## We need to create this Directory + cp $LOGFILE_NAME $LTPROOT/results/ + fi + fi + if [ -d $LTPROOT/output ] ; then + tar -cf ./$TAR_FILE_NAME $LTPROOT/output + if [ $? -eq 0 ]; then + echo "Created TAR File: ./$TAR_FILE_NAME successfully, added $LTPROOT/output" + else + echo "Cannot Create TAR File: ./$TAR_FILE_NAME for adding $LTPROOT/output" + fi + fi + if [ -d $LTPROOT/results ] ; then + tar -uf ./$TAR_FILE_NAME $LTPROOT/results + if [ $? -eq 0 ]; then + echo "Updated TAR File: ./$TAR_FILE_NAME successfully, added $LTPROOT/results" + else + echo "Cannot Update TAR File: ./$TAR_FILE_NAME for adding $LTPROOT/results" + fi + fi + if [ -e $LTPROOT/nohup.out ] ; then ## If User would have Chosen nohup to do ltprun + tar -uf ./$TAR_FILE_NAME $LTPROOT/nohup.out + if [ $? -eq 0 ]; then + echo "Updated TAR File: ./$TAR_FILE_NAME successfully, added $LTPROOT/nohup.out" + else + echo "Cannot Update TAR File: ./$TAR_FILE_NAME for adding $LTPROOT/nohup.out" + fi + fi + gzip ./$TAR_FILE_NAME ## gzip this guy + if [ $? -eq 0 ]; then + echo "Gunzipped TAR File: ./$TAR_FILE_NAME" + else + echo "Cannot Gunzip TAR File: ./$TAR_FILE_NAME" + fi + if [ -e /usr/bin/mutt ] ; then ## This is a better mail client than others + echo "Starting mailing reports to: $EMAIL_TO, file: ./$TAR_FILE_NAME.gz" + mutt -a ./$TAR_FILE_NAME.gz -s "LTP Reports on $test_start_time" $EMAIL_TO < /dev/null + if [ $? -eq 0 ]; then + echo "Reports Successfully mailed to: $EMAIL_TO" + else + echo "Reports cannot be mailed to: $EMAIL_TO" + fi + else ## Use our Ageold mail program + echo "Starting mailing reports to: $EMAIL_TO, file: ./$TAR_FILE_NAME.gz" + uuencode ./$TAR_FILE_NAME.gz $TAR_FILE_NAME.gz | mail $EMAIL_TO -s "LTP Reports on $test_start_time" + if [ $? -eq 0 ]; then + echo "Reports Successfully mailed to: $EMAIL_TO" + else + echo "Reports cannot be mailed to: $EMAIL_TO" + fi + fi + fi + fi + + [ ! -z "$QUIET_MODE" ] && { echo "INFO: Test end time: $(date)" ; } + + [ "$GENLOAD" -eq 1 ] && { killall -9 genload >/dev/null 2>&1; } + [ "$NETPIPE" -eq 1 ] && { killall -9 NPtcp >/dev/null 2>&1; } + + [ "$ALT_DIR_OUT" -eq 1 ] || [ "$ALT_DIR_RES" -eq 1 ] && \ + { + cat <<-EOF >&1 + + ###############################################################" + + Done executing testcases." + LTP Version: $version_date + ###############################################################" + + EOF + } + exit $VALUE +} + +cleanup() +{ + rm -rf ${TMP} +} + +trap "cleanup" 0 +setup +main "$@" + +#vim: syntax=sh diff --git a/ltp_framework/ver_linux b/ltp_framework/ver_linux new file mode 100755 index 0000000..71cbb08 --- /dev/null +++ b/ltp_framework/ver_linux @@ -0,0 +1,89 @@ +#!/bin/sh +# Before running this script please ensure that your PATH is +# typical as you use for compilation/istallation. I use +# /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may +# differ on your system. +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH +echo 'If some fields are empty or look unusual you may have an old version.' +echo 'Compare to the current minimal requirements in Documentation/Changes.' +echo ' ' + +cat /etc/*release 2> /dev/null +if [ $? = 1 ]; then + echo '/etc/issue:' + cat /etc/issue 2> /dev/null +fi + +uname -a +echo ' ' + +echo "Gnu C " `gcc --version 2>/dev/null | head -n 1` + +make --version 2>&1 | awk -F, '{print $1}' | awk \ + '/GNU Make/{print "Gnu make ",$NF}' + +ld -v 2>&1 | awk -F\) '{print $1}' | awk \ + '/BFD/{print "binutils ",$NF}' + +fdformat --version 2>&1 | awk -F\- '{print "util-linux ", $NF}' + +mount --version 2>&1 | awk -F\- '{print "mount ", $NF}' + +insmod -V 2>&1 | awk 'NR==1 {print "modutils ",$NF}' + +tune2fs 2>&1 | grep "^tune2fs" | sed 's/,//' | awk \ +'NR==1 {print "e2fsprogs ", $2}' + +reiserfsck 2>&1 | grep reiserfsprogs | awk \ +'NR==1{print "reiserfsprogs ", $NF}' + +cardmgr -V 2>&1| grep version | awk \ +'NR==1{print "pcmcia-cs ", $3}' + +pppd --version 2>&1| grep version | awk \ +'NR==1{print "PPP ", $3}' + +isdnctrl 2>&1 | grep version | awk \ +'NR==1{print "isdn4k-utils ", $NF}' + +ls -l `ldd /bin/sh | awk '/libc/{print $3}'` | sed \ +-e 's/\.so$//' | awk -F'[.-]' '{print "Linux C Library " \ +$(NF-2)"."$(NF-1)"."$NF}' + +ldd -v > /dev/null 2>&1 && ldd -v || ldd --version |head -n 1 | awk \ +'NR==1{print "Dynamic linker (ldd) ", $NF}' + +ls -l /usr/lib/lib{g,stdc}++.so 2>/dev/null | awk -F. \ + '{print "Linux C++ Library " $4"."$5"."$6}' + +ps --version 2>&1 | awk 'NR==1{print "Procps ", $NF}' + +ifconfig --version 2>&1 | grep tools | awk \ +'NR==1{print "Net-tools ", $NF}' + +ip -V 2>&1 | awk \ +'NR==1{print "iproute2 ", $NF}' + +# Kbd needs 'loadkeys -h', +loadkeys -h 2>&1 | awk \ +'(NR==1 && ($3 !~ /option/)) {print "Kbd ", $3}' + +# while console-tools needs 'loadkeys -V'. +loadkeys -V 2>&1 | awk \ +'(NR==1 && ($2 ~ /console-tools/)) {print "Console-tools ", $3}' + +expr --v 2>&1 | awk 'NR==1{print "Sh-utils ", $NF}' + +if [ -e /proc/modules ]; then + X=`cat /proc/modules | sed -e "s/ .*$//"` + echo "Modules Loaded "$X +fi + +echo +echo 'free reports:' +free + +echo +echo '/proc/cpuinfo' +cat /proc/cpuinfo -- cgit v1.2.3