/*1* Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89/*10* This file is dual-licensed and is also available under the following11* terms:12*13* Copyright (c) 2004, Richard Levitte <[email protected]>14* All rights reserved.15*16* Redistribution and use in source and binary forms, with or without17* modification, are permitted provided that the following conditions18* are met:19* 1. Redistributions of source code must retain the above copyright20* notice, this list of conditions and the following disclaimer.21* 2. Redistributions in binary form must reproduce the above copyright22* notice, this list of conditions and the following disclaimer in the23* documentation and/or other materials provided with the distribution.24*25* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS26* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT27* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR28* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT29* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,30* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT31* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,32* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY33* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT34* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE35* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.36*/3738#include <stddef.h>39#include <stdlib.h>40#include <string.h>41#include <errno.h>42#include <descrip.h>43#include <namdef.h>44#include <rmsdef.h>45#include <libfildef.h>46#include <lib$routines.h>47#include <strdef.h>48#include <str$routines.h>49#include <stsdef.h>50#ifndef LPDIR_H51# include "LPdir.h"52#endif53#include "vms_rms.h"5455/* Some compiler options hide EVMSERR. */56#ifndef EVMSERR57# define EVMSERR 65535 /* error for non-translatable VMS errors */58#endif5960struct LP_dir_context_st {61unsigned long VMS_context;62char filespec[NAMX_MAXRSS + 1];63char result[NAMX_MAXRSS + 1];64struct dsc$descriptor_d filespec_dsc;65struct dsc$descriptor_d result_dsc;66};6768const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)69{70int status;71char *p, *r;72size_t l;73unsigned long flags = 0;7475/* Arrange 32-bit pointer to (copied) string storage, if needed. */76#if __INITIAL_POINTER_SIZE == 6477# pragma pointer_size save78# pragma pointer_size 3279char *ctx_filespec_32p;80# pragma pointer_size restore81char ctx_filespec_32[NAMX_MAXRSS + 1];82#endif /* __INITIAL_POINTER_SIZE == 64 */8384#ifdef NAML$C_MAXRSS85flags |= LIB$M_FIL_LONG_NAMES;86#endif8788if (ctx == NULL || directory == NULL) {89errno = EINVAL;90return 0;91}9293errno = 0;94if (*ctx == NULL) {95size_t filespeclen = strlen(directory);96char *filespec = NULL;9798if (filespeclen == 0) {99errno = ENOENT;100return 0;101}102103/* MUST be a VMS directory specification! Let's estimate if it is. */104if (directory[filespeclen - 1] != ']'105&& directory[filespeclen - 1] != '>'106&& directory[filespeclen - 1] != ':') {107errno = EINVAL;108return 0;109}110111filespeclen += 4; /* "*.*;" */112113if (filespeclen > NAMX_MAXRSS) {114errno = ENAMETOOLONG;115return 0;116}117118*ctx = malloc(sizeof(**ctx));119if (*ctx == NULL) {120errno = ENOMEM;121return 0;122}123memset(*ctx, 0, sizeof(**ctx));124125strcpy((*ctx)->filespec, directory);126strcat((*ctx)->filespec, "*.*;");127128/* Arrange 32-bit pointer to (copied) string storage, if needed. */129#if __INITIAL_POINTER_SIZE == 64130# define CTX_FILESPEC ctx_filespec_32p131/* Copy the file name to storage with a 32-bit pointer. */132ctx_filespec_32p = ctx_filespec_32;133strcpy(ctx_filespec_32p, (*ctx)->filespec);134#else /* __INITIAL_POINTER_SIZE == 64 */135# define CTX_FILESPEC (*ctx)->filespec136#endif /* __INITIAL_POINTER_SIZE == 64 [else] */137138(*ctx)->filespec_dsc.dsc$w_length = filespeclen;139(*ctx)->filespec_dsc.dsc$b_dtype = DSC$K_DTYPE_T;140(*ctx)->filespec_dsc.dsc$b_class = DSC$K_CLASS_S;141(*ctx)->filespec_dsc.dsc$a_pointer = CTX_FILESPEC;142}143144(*ctx)->result_dsc.dsc$w_length = 0;145(*ctx)->result_dsc.dsc$b_dtype = DSC$K_DTYPE_T;146(*ctx)->result_dsc.dsc$b_class = DSC$K_CLASS_D;147(*ctx)->result_dsc.dsc$a_pointer = 0;148149status = lib$find_file(&(*ctx)->filespec_dsc, &(*ctx)->result_dsc,150&(*ctx)->VMS_context, 0, 0, 0, &flags);151152if (status == RMS$_NMF) {153errno = 0;154vaxc$errno = status;155return NULL;156}157158if (!$VMS_STATUS_SUCCESS(status)) {159errno = EVMSERR;160vaxc$errno = status;161return NULL;162}163164/*165* Quick, cheap and dirty way to discard any device and directory, since166* we only want file names167*/168l = (*ctx)->result_dsc.dsc$w_length;169p = (*ctx)->result_dsc.dsc$a_pointer;170r = p;171for (; *p; p++) {172if (*p == '^' && p[1] != '\0') { /* Take care of ODS-5 escapes */173p++;174} else if (*p == ':' || *p == '>' || *p == ']') {175l -= p + 1 - r;176r = p + 1;177} else if (*p == ';') {178l = p - r;179break;180}181}182183strncpy((*ctx)->result, r, l);184(*ctx)->result[l] = '\0';185str$free1_dx(&(*ctx)->result_dsc);186187return (*ctx)->result;188}189190int LP_find_file_end(LP_DIR_CTX **ctx)191{192if (ctx != NULL && *ctx != NULL) {193int status = lib$find_file_end(&(*ctx)->VMS_context);194195free(*ctx);196197if (!$VMS_STATUS_SUCCESS(status)) {198errno = EVMSERR;199vaxc$errno = status;200return 0;201}202return 1;203}204errno = EINVAL;205return 0;206}207208209