Home | History | Annotate | Download | only in diskomizer
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 #pragma ident	"@(#)daio.c	1.10	09/05/26 SMI"
     23 
     24 /*
     25  *	Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     26  *	Use is subject to license terms.
     27  */
     28 
     29 /*
     30  *	diskomizer async io abstraction.
     31  */
     32 #include <diskomizer/daio.h>
     33 #include <stdlib.h>
     34 #include <ctype.h>
     35 #include <strings.h>
     36 #include <dlfcn.h>
     37 #include <stdio.h>
     38 
     39 TNF_DEFINE_RECORD_2(daio_aio_result_t, daio_tnf_aio_result,
     40 	tnf_longlong, daio_return,
     41 	tnf_uint, daio_errno)
     42 TNF_DEFINE_RECORD_2(daio_result_t, daio_tnf_result,
     43 	tnf_longlong, result.daio_return,
     44 	tnf_uint, result.daio_errno)
     45 
     46 static struct daio_ops *
     47 do_dlopen(const char *name)
     48 {
     49 	void * handle;
     50 	if ((handle = dlopen(name, RTLD_NOW)) != NULL) {
     51 		struct daio_ops *ops;
     52 
     53 		if ((ops = dlsym(handle, DAIO_OPS_STRING)) == NULL) {
     54 			dlclose(handle);
     55 		} else {
     56 			return (ops);
     57 		}
     58 	}
     59 	return (NULL);
     60 }
     61 static void
     62 lower(char *x)
     63 {
     64 	while (*x != NULL) {
     65 		*x = tolower(*x);
     66 		x++;
     67 	}
     68 }
     69 static const char libdaio_name[] = "libdaio_%s.so";
     70 
     71 static struct daio_ops *
     72 open_daio(char *libname, const char *name)
     73 {
     74 	sprintf(libname, libdaio_name, name);
     75 	lower(libname);
     76 	return (do_dlopen(libname));
     77 }
     78 
     79 struct daio_ops *
     80 daio_choose_ops(const char *name)
     81 {
     82 	struct daio_ops *ops = NULL;
     83 	char *x = (char *)name;
     84 
     85 	if ((ops = do_dlopen(name)) != NULL) {
     86 		return (ops);
     87 	} else {
     88 		char *full_name;
     89 		/*
     90 		 * Have to allocate enough space for the string in 'name'
     91 		 * and the string "libdaio_%s.so" and the trailing NULL.
     92 		 */
     93 		if ((full_name = malloc(strlen(name) +
     94 		    strlen(libdaio_name) + 1)) != NULL) {
     95 			x = full_name;
     96 			ops = open_daio(full_name, name);
     97 			if (ops == NULL) {
     98 				char *tname;
     99 
    100 				tname = strdup(name);
    101 				if (tname != NULL) {
    102 					char *space;
    103 					char again = 0;
    104 
    105 					space = strchr(tname, ' ');
    106 					if (space != NULL) {
    107 						*space = NULL;
    108 						again = 1;
    109 					}
    110 					space = strchr(tname, '\t');
    111 					if (space != NULL) {
    112 						*space = NULL;
    113 						again = 1;
    114 					}
    115 					if (again) {
    116 						ops = open_daio(full_name,
    117 						    tname);
    118 					}
    119 					free(tname);
    120 				}
    121 			}
    122 		}
    123 	}
    124 	if (ops == NULL) {
    125 		fprintf(stderr, "Err %s: %s\n", x, dlerror());
    126 	}
    127 	if (name != x) {
    128 		free(x);
    129 	}
    130 	return (ops);
    131 }
    132