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