⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldif.c

📁 ldap服务器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ldif.c - the ldif backend *//* $OpenLDAP: pkg/ldap/servers/slapd/back-ldif/ldif.c,v 1.1.2.22 2007/01/02 21:44:03 kurt Exp $ *//* This work is part of OpenLDAP Software <http://www.openldap.org/>. * * Copyright 2005-2007 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * <http://www.OpenLDAP.org/license.html>. *//* ACKNOWLEDGEMENTS: * This work was originally developed by Eric Stokes for inclusion * in OpenLDAP Software. */#include "portable.h"#include <stdio.h>#include <ac/string.h>#include <sys/types.h>#include <sys/stat.h>#include <ac/dirent.h>#include <fcntl.h>#include <ac/errno.h>#include <ac/unistd.h>#include "slap.h"#include "lutil.h"#include "config.h"typedef struct enumCookie {	Operation *op;	SlapReply *rs;	Entry **entries;	int elen;	int eind;} enumCookie;struct ldif_info {	struct berval li_base_path;	enumCookie li_tool_cookie;	ID li_tool_current;	ldap_pvt_thread_rdwr_t  li_rdwr;};#ifdef _WIN32#define mkdir(a,b)	mkdir(a)#endif#define LDIF	".ldif"#define IX_DNL	'{'#define	IX_DNR	'}'#ifndef IX_FSL#define	IX_FSL	IX_DNL#define IX_FSR	IX_DNR#endif#define ENTRY_BUFF_INCREMENT 500static ConfigTable ldifcfg[] = {	{ "directory", "dir", 2, 2, 0, ARG_BERVAL|ARG_OFFSET,		(void *)offsetof(struct ldif_info, li_base_path),		"( OLcfgDbAt:0.1 NAME 'olcDbDirectory' "			"DESC 'Directory for database content' "			"EQUALITY caseIgnoreMatch "			"SYNTAX OMsDirectoryString )", NULL, NULL },	{ NULL, NULL, 0, 0, 0, ARG_IGNORED,		NULL, NULL, NULL, NULL }};static ConfigOCs ldifocs[] = {	{ "( OLcfgDbOc:2.1 "		"NAME 'olcLdifConfig' "		"DESC 'LDIF backend configuration' "		"SUP olcDatabaseConfig "		"MUST ( olcDbDirectory ) )", Cft_Database, ldifcfg },	{ NULL, 0, NULL }};static voiddn2path(struct berval * dn, struct berval * suffixdn, struct berval * base_path,	struct berval *res){	char *ptr, *sep, *end;	assert( dn != NULL );	assert( !BER_BVISNULL( dn ) );	assert( suffixdn != NULL );	assert( !BER_BVISNULL( suffixdn ) );	assert( dnIsSuffix( dn, suffixdn ) );	res->bv_len = dn->bv_len + base_path->bv_len + 1 + STRLENOF( LDIF );	res->bv_val = ch_malloc( res->bv_len + 1 );	ptr = lutil_strcopy( res->bv_val, base_path->bv_val );	*ptr++ = LDAP_DIRSEP[0];	ptr = lutil_strcopy( ptr, suffixdn->bv_val );	end = dn->bv_val + dn->bv_len - suffixdn->bv_len - 1;	while ( end > dn->bv_val ) {		for (sep = end-1; sep >=dn->bv_val && !DN_SEPARATOR( *sep ); sep--);		*ptr++ = LDAP_DIRSEP[0];		ptr = lutil_strncopy( ptr, sep+1, end-sep-1 );		end = sep;	}	strcpy(ptr, LDIF);#if IX_FSL != IX_DNL	ptr = res->bv_val;	while( ptr=strchr(ptr, IX_DNL) ) {		*ptr++ = IX_FSL;		ptr = strchr(ptr, IX_DNR);		if ( ptr )			*ptr++ = IX_FSR;		else			break;	}#endif}static char * slurp_file(int fd) {	int read_chars_total = 0;	int read_chars = 0;	int entry_size;	char * entry;	char * entry_pos;	struct stat st;	fstat(fd, &st);	entry_size = st.st_size;	entry = ch_malloc( entry_size+1 );	entry_pos = entry;		while(1) {		read_chars = read(fd, (void *) entry_pos, entry_size - read_chars_total);		if(read_chars == -1) {			SLAP_FREE(entry);			return NULL;		}		if(read_chars == 0) {			entry[read_chars_total] = '\0';			break;		}		else {			read_chars_total += read_chars;			entry_pos += read_chars;		}	}	return entry;}static int spew_file(int fd, char * spew, int len) {	int writeres = 0;		while(len > 0) {		writeres = write(fd, spew, len);		if(writeres == -1) {			Debug( LDAP_DEBUG_ANY, "could not spew write: %s\n",				STRERROR( errno ), 0, 0 );			return -1;		}		else {			spew += writeres;			len -= writeres;		}	}	return writeres;}static int spew_entry(Entry * e, struct berval * path) {	int rs;	int openres;	int spew_res;	int entry_length;	char * entry_as_string;	openres = open(path->bv_val, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR | S_IWUSR);	if(openres == -1) {		if(errno == ENOENT)			rs = LDAP_NO_SUCH_OBJECT;		else			rs = LDAP_UNWILLING_TO_PERFORM;		Debug( LDAP_DEBUG_ANY, "could not open \"%s\": %s\n",			path->bv_val, STRERROR( errno ), 0 );	}	else {		struct berval rdn;		int tmp;		/* Only save the RDN onto disk */		dnRdn( &e->e_name, &rdn );		if ( rdn.bv_len != e->e_name.bv_len ) {			e->e_name.bv_val[rdn.bv_len] = '\0';			tmp = e->e_name.bv_len;			e->e_name.bv_len = rdn.bv_len;			rdn.bv_len = tmp;		}		entry_as_string = entry2str(e, &entry_length);		/* Restore full DN */		if ( rdn.bv_len != e->e_name.bv_len ) {			e->e_name.bv_val[e->e_name.bv_len] = ',';			e->e_name.bv_len = rdn.bv_len;		}		if(entry_as_string == NULL) {			rs = LDAP_UNWILLING_TO_PERFORM;			close(openres);		}		else {			spew_res = spew_file(openres, entry_as_string, entry_length);			close(openres);			if(spew_res == -1)				rs = LDAP_UNWILLING_TO_PERFORM;			else				rs = LDAP_SUCCESS;		}	}	return rs;}static Entry * get_entry_for_fd(int fd,	struct berval *pdn,	struct berval *pndn){	char * entry = (char *) slurp_file(fd);	Entry * ldentry = NULL;		/* error reading file */	if(entry == NULL) {		goto return_value;	}	ldentry = str2entry(entry);	if ( ldentry ) {		struct berval rdn;		rdn = ldentry->e_name;		build_new_dn( &ldentry->e_name, pdn, &rdn, NULL );		ch_free( rdn.bv_val );		rdn = ldentry->e_nname;		build_new_dn( &ldentry->e_nname, pndn, &rdn, NULL );		ch_free( rdn.bv_val );	} return_value:	if(fd != -1) {		if(close(fd) != 0) {			/* log error */		}	}	if(entry != NULL)		SLAP_FREE(entry);	return ldentry;}static Entry * get_entry(Operation *op, struct berval *base_path) {	struct berval path, pdn, pndn;	int fd;	dnParent(&op->o_req_dn, &pdn);	dnParent(&op->o_req_ndn, &pndn);	dn2path(&op->o_req_ndn, op->o_bd->be_nsuffix, base_path, &path);	fd = open(path.bv_val, O_RDONLY);	/* error opening file (mebbe should log error) */	if ( fd == -1 && ( errno != ENOENT || op->o_tag != LDAP_REQ_ADD ) ) {		Debug( LDAP_DEBUG_ANY, "failed to open file \"%s\": %s\n",			path.bv_val, STRERROR(errno), 0 );	}	if(path.bv_val != NULL)		SLAP_FREE(path.bv_val);	if ( fd != -1 ) {		return get_entry_for_fd(fd, &pdn, &pndn);	}	return NULL;}static void fullpath(struct berval *base, struct berval *name, struct berval *res) {	char *ptr;	res->bv_len = name->bv_len + base->bv_len + 1;	res->bv_val = ch_malloc( res->bv_len + 1 );	strcpy(res->bv_val, base->bv_val);	ptr = res->bv_val + base->bv_len;	*ptr++ = LDAP_DIRSEP[0];	strcpy(ptr, name->bv_val);}typedef struct bvlist {	struct bvlist *next;	struct berval bv;	struct berval num;	unsigned int inum;	int off;} bvlist;static int r_enum_tree(enumCookie *ck, struct berval *path,	struct berval *pdn, struct berval *pndn){	Entry *e;	int fd, rc = LDAP_SUCCESS;	fd = open( path->bv_val, O_RDONLY );	if ( fd < 0 ) {		Debug( LDAP_DEBUG_ANY,			"=> ldif_enum_tree: failed to open %s: %s\n",			path->bv_val, STRERROR(errno), 0 );		return LDAP_NO_SUCH_OBJECT;	}	e = get_entry_for_fd(fd, pdn, pndn);	if ( !e ) {		Debug( LDAP_DEBUG_ANY,			"=> ldif_enum_tree: failed to read entry for %s\n",			path->bv_val, 0, 0 );		return LDAP_BUSY;	}	if ( ck->op->ors_scope == LDAP_SCOPE_BASE ||		ck->op->ors_scope == LDAP_SCOPE_SUBTREE ) {		/* Send right away? */		if ( ck->rs ) {			/*			 * if it's a referral, add it to the list of referrals. only do			 * this for non-base searches, and don't check the filter			 * explicitly here since it's only a candidate anyway.			 */			if ( !get_manageDSAit( ck->op )					&& ck->op->ors_scope != LDAP_SCOPE_BASE					&& is_entry_referral( e ) )			{				BerVarray erefs = get_entry_referrals( ck->op, e );				ck->rs->sr_ref = referral_rewrite( erefs,						&e->e_name, NULL,						ck->op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL							? LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );				ck->rs->sr_entry = e;				rc = send_search_reference( ck->op, ck->rs );				ber_bvarray_free( ck->rs->sr_ref );				ber_bvarray_free( erefs );				ck->rs->sr_ref = NULL;				ck->rs->sr_entry = NULL;			} else if ( test_filter( ck->op, e, ck->op->ors_filter ) == LDAP_COMPARE_TRUE )			{				ck->rs->sr_entry = e;				ck->rs->sr_attrs = ck->op->ors_attrs;				ck->rs->sr_flags = REP_ENTRY_MODIFIABLE;				rc = send_search_entry(ck->op, ck->rs);				ck->rs->sr_entry = NULL;			}			fd = 1;			if ( rc )				goto done;		} else {		/* Queueing up for tool mode */			if(ck->entries == NULL) {				ck->entries = (Entry **) ch_malloc(sizeof(Entry *) * ENTRY_BUFF_INCREMENT);				ck->elen = ENTRY_BUFF_INCREMENT;			}			if(ck->eind >= ck->elen) { /* grow entries if necessary */					ck->entries = (Entry **) ch_realloc(ck->entries, sizeof(Entry *) * (ck->elen) * 2);				ck->elen *= 2;			}			ck->entries[ck->eind++] = e;			fd = 0;		}	} else {		fd = 1;	}	if ( ck->op->ors_scope != LDAP_SCOPE_BASE ) {		DIR * dir_of_path;		bvlist *list = NULL, *ptr;		path->bv_len -= STRLENOF( LDIF );		path->bv_val[path->bv_len] = '\0';		dir_of_path = opendir(path->bv_val);		if(dir_of_path == NULL) { /* can't open directory */			if ( errno != ENOENT ) {				/* it shouldn't be treated as an error				 * only if the directory doesn't exist */				rc = LDAP_BUSY;				Debug( LDAP_DEBUG_ANY,					"=> ldif_enum_tree: failed to opendir %s (%d)\n",					path->bv_val, errno, 0 );			}			goto done;		}			while(1) {			struct berval fname, itmp;			struct dirent * dir;			bvlist *bvl, **prev;			dir = readdir(dir_of_path);			if(dir == NULL) break; /* end of the directory */			fname.bv_len = strlen( dir->d_name );			if ( fname.bv_len <= STRLENOF( LDIF ))				continue;			if ( strcmp( dir->d_name + (fname.bv_len - STRLENOF(LDIF)), LDIF))				continue;			fname.bv_val = dir->d_name;			bvl = ch_malloc( sizeof(bvlist) );			ber_dupbv( &bvl->bv, &fname );			BER_BVZERO( &bvl->num );			itmp.bv_val = strchr( bvl->bv.bv_val, IX_FSL );			if ( itmp.bv_val ) {				char *ptr;				itmp.bv_val++;				ptr = strchr( itmp.bv_val, IX_FSR );				if ( ptr ) {					itmp.bv_len = ptr - itmp.bv_val;					ber_dupbv( &bvl->num, &itmp );					bvl->inum = strtol( itmp.bv_val, NULL, 0 );					itmp.bv_val[0] = '\0';					bvl->off = itmp.bv_val - bvl->bv.bv_val;				}			}			for (prev = &list; (ptr = *prev) != NULL; prev = &ptr->next) {				int cmp = strcmp( bvl->bv.bv_val, ptr->bv.bv_val );				if ( !cmp && bvl->num.bv_val )					cmp = bvl->inum - ptr->inum;				if ( cmp < 0 )					break;			}			*prev = bvl;			bvl->next = ptr;						}		closedir(dir_of_path);		if (ck->op->ors_scope == LDAP_SCOPE_ONELEVEL)			ck->op->ors_scope = LDAP_SCOPE_BASE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -