mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
ITS#5408 part 9 - Sorted RDNs.
- Parse sorted attrs more carefully: Accept only attr={num}val.ldif and attr=val{num}.ldif and only base 10. Sort "attr=foo" before "attr=foo{n}". Truncate at ".ldif" while sorting. - Make the sort order independent of the LDIF files' order in the directory.
This commit is contained in:
parent
32bc29d1af
commit
c765070bf0
@ -137,6 +137,7 @@ struct ldif_info {
|
||||
|
||||
/* Collect other "safe char" tests here, until someone needs a fix. */
|
||||
enum {
|
||||
eq_unsafe = LDIF_UNSAFE_CHAR('='),
|
||||
safe_filenames = STRLENOF("" LDAP_DIRSEP "") == 1 && !(
|
||||
LDIF_UNSAFE_CHAR('-') || /* for "{-1}frontend" in bconfig.c */
|
||||
LDIF_UNSAFE_CHAR(LDIF_ESCAPE_CHAR) ||
|
||||
@ -565,11 +566,14 @@ get_entry(
|
||||
|
||||
/*
|
||||
* RDN-named directory entry, with special handling of "attr={num}val" RDNs.
|
||||
* For sorting, filename "attr=val.ldif" is truncated to "attr="val\0ldif",
|
||||
* and filename "attr={num}val.ldif" to "attr={\0um}val.ldif".
|
||||
* Does not sort escaped chars correctly, would need to un-escape them.
|
||||
*/
|
||||
typedef struct bvlist {
|
||||
struct bvlist *next;
|
||||
char *trunc; /* filename was truncated here */
|
||||
int inum; /* num from "attr={num}" in filename, if any */
|
||||
int inum; /* num from "attr={num}" in filename, or INT_MIN */
|
||||
char savech; /* original char at *trunc */
|
||||
char fname; /* variable length array BVL_NAME(bvl) = &fname */
|
||||
# define BVL_NAME(bvl) ((char *) (bvl) + offsetof(bvlist, fname))
|
||||
@ -667,10 +671,10 @@ ldif_readdir(
|
||||
while ( (dir = readdir( dir_of_path )) != NULL ) {
|
||||
size_t fname_len;
|
||||
bvlist *bvl, **prev;
|
||||
char *idxp, *endp;
|
||||
char *trunc, *idxp, *endp, *endp2;
|
||||
|
||||
fname_len = strlen( dir->d_name );
|
||||
if ( fname_len <= STRLENOF( LDIF ))
|
||||
if ( fname_len < STRLENOF( "x=" LDIF )) /* min filename size */
|
||||
continue;
|
||||
if ( strcmp( dir->d_name + fname_len - STRLENOF(LDIF), LDIF ))
|
||||
continue;
|
||||
@ -685,22 +689,28 @@ ldif_readdir(
|
||||
}
|
||||
strcpy( BVL_NAME( bvl ), dir->d_name );
|
||||
|
||||
bvl->savech = '\0';
|
||||
if ( (idxp = strchr( BVL_NAME( bvl ), IX_FSL )) != NULL &&
|
||||
(endp = strchr( ++idxp, IX_FSR )) != NULL )
|
||||
/* Make it sortable by ("attr=val" or <preceding {num}, num>) */
|
||||
trunc = BVL_NAME( bvl ) + fname_len - STRLENOF( LDIF );
|
||||
if ( (idxp = strchr( BVL_NAME( bvl ) + 2, IX_FSL )) != NULL &&
|
||||
(endp = strchr( ++idxp, IX_FSR )) != NULL && endp > idxp &&
|
||||
(eq_unsafe || idxp[-2] == '=' || endp + 1 == trunc) )
|
||||
{
|
||||
/* attr={n}val or bconfig.c's "pseudo-indexed" attr=val{n} */
|
||||
bvl->inum = strtol( idxp, NULL, 0 );
|
||||
bvl->trunc = idxp;
|
||||
bvl->savech = *idxp;
|
||||
*idxp = '\0';
|
||||
bvl->inum = strtol( idxp, &endp2, 10 );
|
||||
if ( endp2 == endp ) {
|
||||
trunc = idxp;
|
||||
goto truncate;
|
||||
}
|
||||
}
|
||||
bvl->inum = INT_MIN;
|
||||
truncate:
|
||||
bvl->trunc = trunc;
|
||||
bvl->savech = *trunc;
|
||||
*trunc = '\0';
|
||||
|
||||
for ( prev = listp; (ptr = *prev) != NULL; prev = &ptr->next ) {
|
||||
int cmp = strcmp( BVL_NAME( bvl ), BVL_NAME( ptr ));
|
||||
if ( !cmp && bvl->savech )
|
||||
cmp = bvl->inum - ptr->inum;
|
||||
if ( cmp < 0 )
|
||||
if ( cmp < 0 || (cmp == 0 && bvl->inum < ptr->inum) )
|
||||
break;
|
||||
}
|
||||
*prev = bvl;
|
||||
@ -776,7 +786,6 @@ ldif_search_entry(
|
||||
ptr = list;
|
||||
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
if ( ptr->savech )
|
||||
*ptr->trunc = ptr->savech;
|
||||
FILL_PATH( &fpath, dir_end, BVL_NAME( ptr ));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user