blob: be0f121277050c4d62a1edc80c597a5c32a3a13d [file] [log] [blame]
Lev Walkin4b102252004-08-19 13:29:18 +00001#include "asn1c_internal.h"
Lev Walkin4efbfb72005-02-25 14:20:30 +00002#include "asn1c_compat.h"
Lev Walkin79f54952004-08-13 16:58:19 +00003
4#ifndef MAXPATHLEN
5#define MAXPATHLEN 1024
6#endif
7
Lev Walkinebfc44d2014-10-12 19:30:12 -07008/* Normally file permissions are (DEFFILEMODE & ~umask(2)) */
Lev Walkin4b102252004-08-19 13:29:18 +00009#ifndef DEFFILEMODE /* Normally in <sys/stat.h> */
Lev Walkinebfc44d2014-10-12 19:30:12 -070010
Lev Walkin93659562010-11-20 09:47:13 -080011#ifdef _WIN32
Lev Walkine751cd82007-11-13 22:30:09 +000012#define DEFFILEMODE (S_IREAD|S_IWRITE)
Lev Walkinebfc44d2014-10-12 19:30:12 -070013#define REASONABLE_FILE_MODE DEFFILEMODE
Lev Walkin4efbfb72005-02-25 14:20:30 +000014#else
Lev Walkin4b102252004-08-19 13:29:18 +000015#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
Lev Walkinebfc44d2014-10-12 19:30:12 -070016#define REASONABLE_FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
17#endif
18#else /* !DEFFILEMODE */
19#ifdef _WIN32
20#define REASONABLE_FILE_MODE DEFFILEMODE
21#else
22#define REASONABLE_FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
Lev Walkin4b102252004-08-19 13:29:18 +000023#endif
Lev Walkin4efbfb72005-02-25 14:20:30 +000024#endif
Lev Walkin4b102252004-08-19 13:29:18 +000025
Lev Walkin50d52cf2013-03-16 08:00:57 -070026#ifdef _WIN32
27int mkstemp(char *template) {
28 char *tmpFN = _mktemp(template);
29 if(tmpFN)
30 return open(tmpFN, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
31 else
32 return -1;
33}
34#undef HAVE_MKSTEMPS
35#endif
36
Lev Walkin27fd0b62007-08-27 23:57:45 +000037#ifdef HAVE_MKSTEMPS
38#undef mkstemp
39#define mkstemp(foo) mkstemps(foo, 0)
40#endif
41
Lev Walkin4b102252004-08-19 13:29:18 +000042FILE *
Lev Walkin4604d032005-03-04 08:52:50 +000043asn1c_open_file(const char *name, const char *ext, char **opt_tmpname) {
Lev Walkin4b102252004-08-19 13:29:18 +000044 int created = 1;
Lev Walkin93659562010-11-20 09:47:13 -080045#ifndef _WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000046 struct stat sb;
Lev Walkin4efbfb72005-02-25 14:20:30 +000047#endif
Lev Walkin4b102252004-08-19 13:29:18 +000048 char *fname;
Lev Walkin4efbfb72005-02-25 14:20:30 +000049 size_t len;
Lev Walkin4b102252004-08-19 13:29:18 +000050 FILE *fp;
Lev Walkin4604d032005-03-04 08:52:50 +000051 int ret;
Lev Walkin4b102252004-08-19 13:29:18 +000052 int fd;
53
54 /*
55 * Compute filenames.
56 */
Lev Walkin4604d032005-03-04 08:52:50 +000057 len = strlen(name) + strlen(ext) + sizeof(".XXXXXX");
Lev Walkin4b102252004-08-19 13:29:18 +000058 fname = alloca(len);
Lev Walkin4604d032005-03-04 08:52:50 +000059 ret = snprintf(fname, len, "%s%s%s", name, ext,
60 opt_tmpname ? ".XXXXXX" : "");
Lev Walkinc46b7cb2006-08-18 02:27:55 +000061 assert(ret > 0 && ret < (ssize_t)len);
Lev Walkin4b102252004-08-19 13:29:18 +000062
Lev Walkin4604d032005-03-04 08:52:50 +000063 if(opt_tmpname) {
64 /*
65 * Create temporary file.
66 */
67 fd = mkstemp(fname);
Lev Walkin93659562010-11-20 09:47:13 -080068#ifndef _WIN32
Lev Walkinebfc44d2014-10-12 19:30:12 -070069 /* fchmod() does not respect umask */
70 (void)fchmod(fd, REASONABLE_FILE_MODE);
Lev Walkin4604d032005-03-04 08:52:50 +000071#endif
72 } else {
73 /*
74 * Create specified file, or open the old one.
75 */
76 fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
77 if(fd == -1 && errno == EEXIST) {
78 fd = open(fname, O_WRONLY, DEFFILEMODE);
79 created = 0;
80 }
Lev Walkin4b102252004-08-19 13:29:18 +000081 }
82 if(fd == -1) {
83 perror(fname);
84 return NULL;
85 }
86
Lev Walkin93659562010-11-20 09:47:13 -080087#ifndef _WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000088 /*
89 * Check sanity.
90 */
91 if(fstat(fd, &sb) || !S_ISREG(sb.st_mode)) {
92 fprintf(stderr, "%s: Not a regular file\n", fname);
93 if(created) unlink(fname);
94 close(fd);
95 return NULL;
96 }
97
98 (void)ftruncate(fd, 0);
Lev Walkin4efbfb72005-02-25 14:20:30 +000099#else
100 _chsize(fd, 0);
Lev Walkin93659562010-11-20 09:47:13 -0800101#endif /* _WIN32 */
Lev Walkin4b102252004-08-19 13:29:18 +0000102
103 /*
104 * Convert file descriptor into file pointer.
105 */
106 fp = fdopen(fd, "w");
107 if(fp == NULL) {
108 if(created) unlink(fname);
109 close(fd);
Lev Walkina895afb2005-10-06 10:09:34 +0000110 return NULL;
Lev Walkin4b102252004-08-19 13:29:18 +0000111 }
Lev Walkin4604d032005-03-04 08:52:50 +0000112
113 /* Return the temporary file name */
114 if(opt_tmpname) {
115 *opt_tmpname = strdup(fname);
Lev Walkina895afb2005-10-06 10:09:34 +0000116 if(*opt_tmpname) {
117 /* Successfull */
118 } else {
119 if(created) unlink(fname);
120 fclose(fp);
121 return NULL;
122 }
Lev Walkin4604d032005-03-04 08:52:50 +0000123 }
124
Lev Walkin4b102252004-08-19 13:29:18 +0000125 return fp;
126}
127
128
Lev Walkin79f54952004-08-13 16:58:19 +0000129char *
130a1c_basename(const char *path) {
131 static char strbuf[MAXPATHLEN];
132 const char *pend;
133 const char *name;
134
135 pend = path + strlen(path);
136 if(pend == path) {
137 strcpy(strbuf, ".");
138 return strbuf;
139 }
140
141 /* Skip tailing slashes */
142 for(pend--; pend > path && *pend == '/'; pend--);
143
144 if(pend == path && *path == '/') {
145 strcpy(strbuf, "/");
146 return strbuf;
147 }
148
149 for(name = pend; name > path && name[-1] != '/'; name--);
150
Lev Walkin4b102252004-08-19 13:29:18 +0000151 if((pend - name) >= (int)sizeof(strbuf) - 1) {
Lev Walkin79f54952004-08-13 16:58:19 +0000152 errno = ENAMETOOLONG;
153 return 0;
154 }
155
156 memcpy(strbuf, name, pend - name + 1);
157 strbuf[pend - name + 1] = '\0';
158
159 return strbuf;
160}
161
162
163char *
164a1c_dirname(const char *path) {
165 static char strbuf[MAXPATHLEN];
166 const char *pend;
167 const char *last = 0;
168 int in_slash = 0;
169
170 /* One-pass determination of the last char of the pathname */
171 for(pend = path; ; pend++) {
Lev Walkin79f54952004-08-13 16:58:19 +0000172 switch(*pend) {
173 case '\0': break;
174 case '/':
175 if(!in_slash) {
176 last = pend;
177 in_slash = 1;
178 }
179 continue;
180 default:
181 if(in_slash) in_slash = 0;
182 continue;
183 }
184 break;
185 }
Lev Walkin79f54952004-08-13 16:58:19 +0000186
187 if(last <= path) {
188 strcpy(strbuf, *path == '/' ? "/" : ".");
189 return strbuf;
190 }
191
192 if(!last) {
193 strcpy(strbuf, "/");
194 return strbuf;
195 }
196
Lev Walkin4b102252004-08-19 13:29:18 +0000197 if((last - path) >= (int)sizeof(strbuf)) {
Lev Walkin79f54952004-08-13 16:58:19 +0000198 errno = ENAMETOOLONG;
199 return 0;
200 }
201
202 memcpy(strbuf, path, last - path);
203 strbuf[last - path] = '\0';
204
205 return strbuf;
206}
207