]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - crypto/openssl/crypto/LPdir_vms.c
Fix integer overflow in IGMP protocol. [SA-15:04]
[FreeBSD/releng/9.3.git] / crypto / openssl / crypto / LPdir_vms.c
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
48 struct 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
62 const 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
185 int 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