LPdir_vms.c revision 279265
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{ 50 unsigned long VMS_context; 51#ifdef NAML$C_MAXRSS 52 char filespec[NAML$C_MAXRSS+1]; 53 char result[NAML$C_MAXRSS+1]; 54#else 55 char filespec[256]; 56 char result[256]; 57#endif 58 struct dsc$descriptor_d filespec_dsc; 59 struct dsc$descriptor_d result_dsc; 60}; 61 62const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) 63{ 64 int status; 65 char *p, *r; 66 size_t l; 67 unsigned long flags = 0; 68#ifdef NAML$C_MAXRSS 69 flags |= LIB$M_FIL_LONG_NAMES; 70#endif 71 72 if (ctx == NULL || directory == NULL) 73 { 74 errno = EINVAL; 75 return 0; 76 } 77 78 errno = 0; 79 if (*ctx == NULL) 80 { 81 size_t filespeclen = strlen(directory); 82 char *filespec = NULL; 83 84 if (filespeclen == 0) 85 { 86 errno = ENOENT; 87 return 0; 88 } 89 90 /* MUST be a VMS directory specification! Let's estimate if it is. */ 91 if (directory[filespeclen-1] != ']' 92 && directory[filespeclen-1] != '>' 93 && directory[filespeclen-1] != ':') 94 { 95 errno = EINVAL; 96 return 0; 97 } 98 99 filespeclen += 4; /* "*.*;" */ 100 101 if (filespeclen > 102#ifdef NAML$C_MAXRSS 103 NAML$C_MAXRSS 104#else 105 255 106#endif 107 ) 108 { 109 errno = ENAMETOOLONG; 110 return 0; 111 } 112 113 *ctx = (LP_DIR_CTX *)malloc(sizeof(LP_DIR_CTX)); 114 if (*ctx == NULL) 115 { 116 errno = ENOMEM; 117 return 0; 118 } 119 memset(*ctx, '\0', sizeof(LP_DIR_CTX)); 120 121 strcpy((*ctx)->filespec,directory); 122 strcat((*ctx)->filespec,"*.*;"); 123 (*ctx)->filespec_dsc.dsc$w_length = filespeclen; 124 (*ctx)->filespec_dsc.dsc$b_dtype = DSC$K_DTYPE_T; 125 (*ctx)->filespec_dsc.dsc$b_class = DSC$K_CLASS_S; 126 (*ctx)->filespec_dsc.dsc$a_pointer = (*ctx)->filespec; 127 (*ctx)->result_dsc.dsc$w_length = 0; 128 (*ctx)->result_dsc.dsc$b_dtype = DSC$K_DTYPE_T; 129 (*ctx)->result_dsc.dsc$b_class = DSC$K_CLASS_D; 130 (*ctx)->result_dsc.dsc$a_pointer = 0; 131 } 132 133 (*ctx)->result_dsc.dsc$w_length = 0; 134 (*ctx)->result_dsc.dsc$b_dtype = DSC$K_DTYPE_T; 135 (*ctx)->result_dsc.dsc$b_class = DSC$K_CLASS_D; 136 (*ctx)->result_dsc.dsc$a_pointer = 0; 137 138 status = lib$find_file(&(*ctx)->filespec_dsc, &(*ctx)->result_dsc, 139 &(*ctx)->VMS_context, 0, 0, 0, &flags); 140 141 if (status == RMS$_NMF) 142 { 143 errno = 0; 144 vaxc$errno = status; 145 return NULL; 146 } 147 148 if(!$VMS_STATUS_SUCCESS(status)) 149 { 150 errno = EVMSERR; 151 vaxc$errno = status; 152 return NULL; 153 } 154 155 /* Quick, cheap and dirty way to discard any device and directory, 156 since we only want file names */ 157 l = (*ctx)->result_dsc.dsc$w_length; 158 p = (*ctx)->result_dsc.dsc$a_pointer; 159 r = p; 160 for (; *p; p++) 161 { 162 if (*p == '^' && p[1] != '\0') /* Take care of ODS-5 escapes */ 163 { 164 p++; 165 } 166 else if (*p == ':' || *p == '>' || *p == ']') 167 { 168 l -= p + 1 - r; 169 r = p + 1; 170 } 171 else if (*p == ';') 172 { 173 l = p - r; 174 break; 175 } 176 } 177 178 strncpy((*ctx)->result, r, l); 179 (*ctx)->result[l] = '\0'; 180 str$free1_dx(&(*ctx)->result_dsc); 181 182 return (*ctx)->result; 183} 184 185int LP_find_file_end(LP_DIR_CTX **ctx) 186{ 187 if (ctx != NULL && *ctx != NULL) 188 { 189 int status = lib$find_file_end(&(*ctx)->VMS_context); 190 191 free(*ctx); 192 193 if(!$VMS_STATUS_SUCCESS(status)) 194 { 195 errno = EVMSERR; 196 vaxc$errno = status; 197 return 0; 198 } 199 return 1; 200 } 201 errno = EINVAL; 202 return 0; 203} 204 205