LPdir_vms.c revision 296465
1/* 2 * Copyright (c) 2004, Richard Levitte <richard@levitte.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <stddef.h> 28#include <stdlib.h> 29#include <string.h> 30#include <errno.h> 31#include <descrip.h> 32#include <namdef.h> 33#include <rmsdef.h> 34#include <libfildef.h> 35#include <lib$routines.h> 36#include <strdef.h> 37#include <str$routines.h> 38#include <stsdef.h> 39#ifndef LPDIR_H 40# include "LPdir.h" 41#endif 42 43/* Because some compiler options hide this macor */ 44#ifndef EVMSERR 45# define EVMSERR 65535 /* error for non-translatable VMS errors */ 46#endif 47 48struct LP_dir_context_st { 49 unsigned long VMS_context; 50#ifdef NAML$C_MAXRSS 51 char filespec[NAML$C_MAXRSS + 1]; 52 char result[NAML$C_MAXRSS + 1]; 53#else 54 char filespec[256]; 55 char result[256]; 56#endif 57 struct dsc$descriptor_d filespec_dsc; 58 struct dsc$descriptor_d result_dsc; 59}; 60 61const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) 62{ 63 int status; 64 char *p, *r; 65 size_t l; 66 unsigned long flags = 0; 67#ifdef NAML$C_MAXRSS 68 flags |= LIB$M_FIL_LONG_NAMES; 69#endif 70 71 if (ctx == NULL || directory == NULL) { 72 errno = EINVAL; 73 return 0; 74 } 75 76 errno = 0; 77 if (*ctx == NULL) { 78 size_t filespeclen = strlen(directory); 79 char *filespec = NULL; 80 81 if (filespeclen == 0) { 82 errno = ENOENT; 83 return 0; 84 } 85 86 /* MUST be a VMS directory specification! Let's estimate if it is. */ 87 if (directory[filespeclen - 1] != ']' 88 && directory[filespeclen - 1] != '>' 89 && directory[filespeclen - 1] != ':') { 90 errno = EINVAL; 91 return 0; 92 } 93 94 filespeclen += 4; /* "*.*;" */ 95 96 if (filespeclen > 97#ifdef NAML$C_MAXRSS 98 NAML$C_MAXRSS 99#else 100 255 101#endif 102 ) { 103 errno = ENAMETOOLONG; 104 return 0; 105 } 106 107 *ctx = (LP_DIR_CTX *)malloc(sizeof(LP_DIR_CTX)); 108 if (*ctx == NULL) { 109 errno = ENOMEM; 110 return 0; 111 } 112 memset(*ctx, '\0', sizeof(LP_DIR_CTX)); 113 114 strcpy((*ctx)->filespec, directory); 115 strcat((*ctx)->filespec, "*.*;"); 116 (*ctx)->filespec_dsc.dsc$w_length = filespeclen; 117 (*ctx)->filespec_dsc.dsc$b_dtype = DSC$K_DTYPE_T; 118 (*ctx)->filespec_dsc.dsc$b_class = DSC$K_CLASS_S; 119 (*ctx)->filespec_dsc.dsc$a_pointer = (*ctx)->filespec; 120 (*ctx)->result_dsc.dsc$w_length = 0; 121 (*ctx)->result_dsc.dsc$b_dtype = DSC$K_DTYPE_T; 122 (*ctx)->result_dsc.dsc$b_class = DSC$K_CLASS_D; 123 (*ctx)->result_dsc.dsc$a_pointer = 0; 124 } 125 126 (*ctx)->result_dsc.dsc$w_length = 0; 127 (*ctx)->result_dsc.dsc$b_dtype = DSC$K_DTYPE_T; 128 (*ctx)->result_dsc.dsc$b_class = DSC$K_CLASS_D; 129 (*ctx)->result_dsc.dsc$a_pointer = 0; 130 131 status = lib$find_file(&(*ctx)->filespec_dsc, &(*ctx)->result_dsc, 132 &(*ctx)->VMS_context, 0, 0, 0, &flags); 133 134 if (status == RMS$_NMF) { 135 errno = 0; 136 vaxc$errno = status; 137 return NULL; 138 } 139 140 if (!$VMS_STATUS_SUCCESS(status)) { 141 errno = EVMSERR; 142 vaxc$errno = status; 143 return NULL; 144 } 145 146 /* 147 * Quick, cheap and dirty way to discard any device and directory, since 148 * we only want file names 149 */ 150 l = (*ctx)->result_dsc.dsc$w_length; 151 p = (*ctx)->result_dsc.dsc$a_pointer; 152 r = p; 153 for (; *p; p++) { 154 if (*p == '^' && p[1] != '\0') { /* Take care of ODS-5 escapes */ 155 p++; 156 } else if (*p == ':' || *p == '>' || *p == ']') { 157 l -= p + 1 - r; 158 r = p + 1; 159 } else if (*p == ';') { 160 l = p - r; 161 break; 162 } 163 } 164 165 strncpy((*ctx)->result, r, l); 166 (*ctx)->result[l] = '\0'; 167 str$free1_dx(&(*ctx)->result_dsc); 168 169 return (*ctx)->result; 170} 171 172int LP_find_file_end(LP_DIR_CTX **ctx) 173{ 174 if (ctx != NULL && *ctx != NULL) { 175 int status = lib$find_file_end(&(*ctx)->VMS_context); 176 177 free(*ctx); 178 179 if (!$VMS_STATUS_SUCCESS(status)) { 180 errno = EVMSERR; 181 vaxc$errno = status; 182 return 0; 183 } 184 return 1; 185 } 186 errno = EINVAL; 187 return 0; 188} 189