From a5829ae282f47c39d1dd0642e4a84c0a6f3d80f4 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Sun, 11 Mar 2018 23:48:04 +0100 Subject: [PATCH] Adjust LPdir_unix.c on VMS for OpenSSL expectations When OPENSSL_DIR_read implemented by LPdir_unix.c gets a Unixy path, it will return file names like you'd expect them on Unix. However, if given a path with VMS syntax, such as "[.foo]", it returns file names with generation numbers, such as "bar.txt;1", which makes sense for VMS expectations, but can be surprising for OpenSSL. Our solution is to simply shave off the generation number if OPENSSL_DIR_read() expects there should be one, and make sure not to return the same file name twice. Note that VMS filesystems are case insensitive, so the check for duplicate file names are done without regard to character case. Reviewed-by: Tim Hudson (Merged from https://github.com/openssl/openssl/pull/5587) --- crypto/LPdir_unix.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/crypto/LPdir_unix.c b/crypto/LPdir_unix.c index 6648a60cac..356089d7fd 100644 --- a/crypto/LPdir_unix.c +++ b/crypto/LPdir_unix.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,7 +11,7 @@ * This file is dual-licensed and is also available under the following * terms: * - * Copyright (c) 2004, Richard Levitte + * Copyright (c) 2004, 2018, Richard Levitte * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,6 +46,9 @@ #ifndef LPDIR_H # include "LPdir.h" #endif +#ifdef __VMS +# include +#endif /* * The POSIXly macro for the maximum number of characters in a file path is @@ -73,6 +76,10 @@ struct LP_dir_context_st { DIR *dir; char entry_name[LP_ENTRY_SIZE + 1]; +#ifdef __VMS + int expect_file_generations; + char previous_entry_name[LP_ENTRY_SIZE + 1]; +#endif }; const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) @@ -93,6 +100,15 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) } memset(*ctx, 0, sizeof(**ctx)); +#ifdef __VMS + { + char c = directory[strlen(directory) - 1]; + + if (c == ']' || c == '>' || c == ':') + (*ctx)->expect_file_generations = 1; + } +#endif + (*ctx)->dir = opendir(directory); if ((*ctx)->dir == NULL) { int save_errno = errno; /* Probably not needed, but I'm paranoid */ @@ -103,6 +119,13 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) } } +#ifdef __VMS + strncpy((*ctx)->previous_entry_name, (*ctx)->entry_name, + sizeof((*ctx)->previous_entry_name)); + + again: +#endif + direntry = readdir((*ctx)->dir); if (direntry == NULL) { return 0; @@ -111,6 +134,18 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) strncpy((*ctx)->entry_name, direntry->d_name, sizeof((*ctx)->entry_name) - 1); (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0'; +#ifdef __VMS + if ((*ctx)->expect_file_generations) { + char *p = (*ctx)->entry_name + strlen((*ctx)->entry_name); + + while(p > (*ctx)->entry_name && isdigit(p[-1])) + p--; + if (p > (*ctx)->entry_name && p[-1] == ';') + p[-1] = '\0'; + if (strcasecmp((*ctx)->entry_name, (*ctx)->previous_entry_name) == 0) + goto again; + } +#endif return (*ctx)->entry_name; } -- 2.34.1