1*6b22f423SJonathan Anderson /*- 2*6b22f423SJonathan Anderson * Copyright 2014 Jonathan Anderson. 3*6b22f423SJonathan Anderson * All rights reserved. 4*6b22f423SJonathan Anderson * 5*6b22f423SJonathan Anderson * Redistribution and use in source and binary forms, with or without 6*6b22f423SJonathan Anderson * modification, are permitted provided that the following conditions 7*6b22f423SJonathan Anderson * are met: 8*6b22f423SJonathan Anderson * 1. Redistributions of source code must retain the above copyright 9*6b22f423SJonathan Anderson * notice, this list of conditions and the following disclaimer. 10*6b22f423SJonathan Anderson * 2. Redistributions in binary form must reproduce the above copyright 11*6b22f423SJonathan Anderson * notice, this list of conditions and the following disclaimer in the 12*6b22f423SJonathan Anderson * documentation and/or other materials provided with the distribution. 13*6b22f423SJonathan Anderson * 14*6b22f423SJonathan Anderson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15*6b22f423SJonathan Anderson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16*6b22f423SJonathan Anderson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17*6b22f423SJonathan Anderson * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18*6b22f423SJonathan Anderson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19*6b22f423SJonathan Anderson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20*6b22f423SJonathan Anderson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21*6b22f423SJonathan Anderson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22*6b22f423SJonathan Anderson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23*6b22f423SJonathan Anderson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24*6b22f423SJonathan Anderson * 25*6b22f423SJonathan Anderson * $FreeBSD$ 26*6b22f423SJonathan Anderson */ 27*6b22f423SJonathan Anderson 28*6b22f423SJonathan Anderson #include <atf-c.h> 29*6b22f423SJonathan Anderson #include <fcntl.h> 30*6b22f423SJonathan Anderson #include <stdio.h> 31*6b22f423SJonathan Anderson 32*6b22f423SJonathan Anderson 33*6b22f423SJonathan Anderson struct descriptors { 34*6b22f423SJonathan Anderson int binary; 35*6b22f423SJonathan Anderson int testdir; 36*6b22f423SJonathan Anderson int root; 37*6b22f423SJonathan Anderson int etc; 38*6b22f423SJonathan Anderson int usr; 39*6b22f423SJonathan Anderson }; 40*6b22f423SJonathan Anderson 41*6b22f423SJonathan Anderson static void setup(struct descriptors *); 42*6b22f423SJonathan Anderson static void expect_success(int binary, char *pathfds); 43*6b22f423SJonathan Anderson static void expect_missing_library(int binary, char *pathfds); 44*6b22f423SJonathan Anderson 45*6b22f423SJonathan Anderson static void try_to_run(int binary, int expected_exit_status, 46*6b22f423SJonathan Anderson char * const *env, const char *expected_out, const char *expected_err); 47*6b22f423SJonathan Anderson static int opendir(const char *name); 48*6b22f423SJonathan Anderson static int opendirat(int parent, const char *name); 49*6b22f423SJonathan Anderson 50*6b22f423SJonathan Anderson 51*6b22f423SJonathan Anderson ATF_TC_WITHOUT_HEAD(missing_library); 52*6b22f423SJonathan Anderson ATF_TC_BODY(missing_library, tc) 53*6b22f423SJonathan Anderson { 54*6b22f423SJonathan Anderson struct descriptors files; 55*6b22f423SJonathan Anderson 56*6b22f423SJonathan Anderson setup(&files); 57*6b22f423SJonathan Anderson expect_missing_library(files.binary, NULL); 58*6b22f423SJonathan Anderson } 59*6b22f423SJonathan Anderson 60*6b22f423SJonathan Anderson 61*6b22f423SJonathan Anderson ATF_TC_WITHOUT_HEAD(wrong_library_directories); 62*6b22f423SJonathan Anderson ATF_TC_BODY(wrong_library_directories, tc) 63*6b22f423SJonathan Anderson { 64*6b22f423SJonathan Anderson struct descriptors files; 65*6b22f423SJonathan Anderson char *pathfds; 66*6b22f423SJonathan Anderson 67*6b22f423SJonathan Anderson setup(&files); 68*6b22f423SJonathan Anderson ATF_REQUIRE( 69*6b22f423SJonathan Anderson asprintf(&pathfds, "LD_LIBRARY_PATH_FDS=%d", files.etc) > 0); 70*6b22f423SJonathan Anderson 71*6b22f423SJonathan Anderson expect_missing_library(files.binary, pathfds); 72*6b22f423SJonathan Anderson } 73*6b22f423SJonathan Anderson 74*6b22f423SJonathan Anderson 75*6b22f423SJonathan Anderson ATF_TC_WITHOUT_HEAD(bad_library_directories); 76*6b22f423SJonathan Anderson ATF_TC_BODY(bad_library_directories, tc) 77*6b22f423SJonathan Anderson { 78*6b22f423SJonathan Anderson struct descriptors files; 79*6b22f423SJonathan Anderson char *pathfds; 80*6b22f423SJonathan Anderson 81*6b22f423SJonathan Anderson setup(&files); 82*6b22f423SJonathan Anderson ATF_REQUIRE(asprintf(&pathfds, "::", files.etc) > 0); 83*6b22f423SJonathan Anderson 84*6b22f423SJonathan Anderson expect_missing_library(files.binary, pathfds); 85*6b22f423SJonathan Anderson } 86*6b22f423SJonathan Anderson 87*6b22f423SJonathan Anderson 88*6b22f423SJonathan Anderson ATF_TC_WITHOUT_HEAD(single_library_directory); 89*6b22f423SJonathan Anderson ATF_TC_BODY(single_library_directory, tc) 90*6b22f423SJonathan Anderson { 91*6b22f423SJonathan Anderson struct descriptors files; 92*6b22f423SJonathan Anderson char *pathfds; 93*6b22f423SJonathan Anderson 94*6b22f423SJonathan Anderson setup(&files); 95*6b22f423SJonathan Anderson ATF_REQUIRE( 96*6b22f423SJonathan Anderson asprintf(&pathfds, "LD_LIBRARY_PATH_FDS=%d", files.testdir) > 0); 97*6b22f423SJonathan Anderson 98*6b22f423SJonathan Anderson expect_success(files.binary, pathfds); 99*6b22f423SJonathan Anderson } 100*6b22f423SJonathan Anderson 101*6b22f423SJonathan Anderson 102*6b22f423SJonathan Anderson ATF_TC_WITHOUT_HEAD(first_library_directory); 103*6b22f423SJonathan Anderson ATF_TC_BODY(first_library_directory, tc) 104*6b22f423SJonathan Anderson { 105*6b22f423SJonathan Anderson struct descriptors files; 106*6b22f423SJonathan Anderson char *pathfds; 107*6b22f423SJonathan Anderson 108*6b22f423SJonathan Anderson setup(&files); 109*6b22f423SJonathan Anderson ATF_REQUIRE( 110*6b22f423SJonathan Anderson asprintf(&pathfds, "LD_LIBRARY_PATH_FDS=%d:%d", 111*6b22f423SJonathan Anderson files.testdir, files.etc) > 0); 112*6b22f423SJonathan Anderson 113*6b22f423SJonathan Anderson expect_success(files.binary, pathfds); 114*6b22f423SJonathan Anderson } 115*6b22f423SJonathan Anderson 116*6b22f423SJonathan Anderson 117*6b22f423SJonathan Anderson ATF_TC_WITHOUT_HEAD(middle_library_directory); 118*6b22f423SJonathan Anderson ATF_TC_BODY(middle_library_directory, tc) 119*6b22f423SJonathan Anderson { 120*6b22f423SJonathan Anderson struct descriptors files; 121*6b22f423SJonathan Anderson char *pathfds; 122*6b22f423SJonathan Anderson 123*6b22f423SJonathan Anderson setup(&files); 124*6b22f423SJonathan Anderson ATF_REQUIRE( 125*6b22f423SJonathan Anderson asprintf(&pathfds, "LD_LIBRARY_PATH_FDS=%d:%d:%d", 126*6b22f423SJonathan Anderson files.root, files.testdir, files.usr) > 0); 127*6b22f423SJonathan Anderson 128*6b22f423SJonathan Anderson expect_success(files.binary, pathfds); 129*6b22f423SJonathan Anderson } 130*6b22f423SJonathan Anderson 131*6b22f423SJonathan Anderson 132*6b22f423SJonathan Anderson ATF_TC_WITHOUT_HEAD(last_library_directory); 133*6b22f423SJonathan Anderson ATF_TC_BODY(last_library_directory, tc) 134*6b22f423SJonathan Anderson { 135*6b22f423SJonathan Anderson struct descriptors files; 136*6b22f423SJonathan Anderson char *pathfds; 137*6b22f423SJonathan Anderson 138*6b22f423SJonathan Anderson setup(&files); 139*6b22f423SJonathan Anderson ATF_REQUIRE( 140*6b22f423SJonathan Anderson asprintf(&pathfds, "LD_LIBRARY_PATH_FDS=%d:%d", 141*6b22f423SJonathan Anderson files.root, files.testdir) > 0); 142*6b22f423SJonathan Anderson 143*6b22f423SJonathan Anderson expect_success(files.binary, pathfds); 144*6b22f423SJonathan Anderson } 145*6b22f423SJonathan Anderson 146*6b22f423SJonathan Anderson 147*6b22f423SJonathan Anderson 148*6b22f423SJonathan Anderson /* Register test cases with ATF. */ 149*6b22f423SJonathan Anderson ATF_TP_ADD_TCS(tp) 150*6b22f423SJonathan Anderson { 151*6b22f423SJonathan Anderson ATF_TP_ADD_TC(tp, missing_library); 152*6b22f423SJonathan Anderson ATF_TP_ADD_TC(tp, wrong_library_directories); 153*6b22f423SJonathan Anderson ATF_TP_ADD_TC(tp, bad_library_directories); 154*6b22f423SJonathan Anderson ATF_TP_ADD_TC(tp, single_library_directory); 155*6b22f423SJonathan Anderson ATF_TP_ADD_TC(tp, first_library_directory); 156*6b22f423SJonathan Anderson ATF_TP_ADD_TC(tp, middle_library_directory); 157*6b22f423SJonathan Anderson ATF_TP_ADD_TC(tp, last_library_directory); 158*6b22f423SJonathan Anderson 159*6b22f423SJonathan Anderson return atf_no_error(); 160*6b22f423SJonathan Anderson } 161*6b22f423SJonathan Anderson 162*6b22f423SJonathan Anderson 163*6b22f423SJonathan Anderson static void 164*6b22f423SJonathan Anderson setup(struct descriptors *dp) 165*6b22f423SJonathan Anderson { 166*6b22f423SJonathan Anderson 167*6b22f423SJonathan Anderson ATF_REQUIRE((dp->testdir = opendir(TESTSDIR)) >= 0); 168*6b22f423SJonathan Anderson ATF_REQUIRE( 169*6b22f423SJonathan Anderson (dp->binary = openat(dp->testdir, "target", O_RDONLY)) >= 0); 170*6b22f423SJonathan Anderson 171*6b22f423SJonathan Anderson ATF_REQUIRE((dp->root = opendir("/")) >= 0); 172*6b22f423SJonathan Anderson ATF_REQUIRE((dp->etc = opendirat(dp->root, "etc")) >= 0); 173*6b22f423SJonathan Anderson ATF_REQUIRE((dp->usr = opendirat(dp->root, "usr")) >= 0); 174*6b22f423SJonathan Anderson } 175*6b22f423SJonathan Anderson 176*6b22f423SJonathan Anderson static void 177*6b22f423SJonathan Anderson expect_success(int binary, char *pathfds) 178*6b22f423SJonathan Anderson { 179*6b22f423SJonathan Anderson char * const env[] = { pathfds, NULL }; 180*6b22f423SJonathan Anderson try_to_run(binary, 0, env, "the hypotenuse of 3 and 4 is 5\n", ""); 181*6b22f423SJonathan Anderson } 182*6b22f423SJonathan Anderson 183*6b22f423SJonathan Anderson static void 184*6b22f423SJonathan Anderson expect_missing_library(int binary, char *pathfds) 185*6b22f423SJonathan Anderson { 186*6b22f423SJonathan Anderson char * const env[] = { pathfds, NULL }; 187*6b22f423SJonathan Anderson try_to_run(binary, 1, env, "", 188*6b22f423SJonathan Anderson "Shared object \"libpythagoras.so.0\" not found," 189*6b22f423SJonathan Anderson " required by \"target\"\n"); 190*6b22f423SJonathan Anderson } 191*6b22f423SJonathan Anderson 192*6b22f423SJonathan Anderson 193*6b22f423SJonathan Anderson static void 194*6b22f423SJonathan Anderson try_to_run(int binary, int exit_status, char * const *env, 195*6b22f423SJonathan Anderson const char *expected_out, const char *expected_err) 196*6b22f423SJonathan Anderson { 197*6b22f423SJonathan Anderson pid_t child = atf_utils_fork(); 198*6b22f423SJonathan Anderson 199*6b22f423SJonathan Anderson if (child == 0) { 200*6b22f423SJonathan Anderson char * const args[] = { "target", NULL }; 201*6b22f423SJonathan Anderson 202*6b22f423SJonathan Anderson fexecve(binary, args, env); 203*6b22f423SJonathan Anderson atf_tc_fail("fexecve() failed"); 204*6b22f423SJonathan Anderson } 205*6b22f423SJonathan Anderson 206*6b22f423SJonathan Anderson atf_utils_wait(child, exit_status, expected_out, expected_err); 207*6b22f423SJonathan Anderson } 208*6b22f423SJonathan Anderson 209*6b22f423SJonathan Anderson 210*6b22f423SJonathan Anderson static int 211*6b22f423SJonathan Anderson opendir(const char *name) 212*6b22f423SJonathan Anderson { 213*6b22f423SJonathan Anderson return open(name, O_RDONLY | O_DIRECTORY); 214*6b22f423SJonathan Anderson } 215*6b22f423SJonathan Anderson 216*6b22f423SJonathan Anderson static int 217*6b22f423SJonathan Anderson opendirat(int parent, const char *name) 218*6b22f423SJonathan Anderson { 219*6b22f423SJonathan Anderson return openat(parent, name, O_RDONLY | O_DIRECTORY); 220*6b22f423SJonathan Anderson } 221