blob: ae0f475f81f7c10cd8aec203fa9d1b4465ea5996 [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
Lev Walkina4f8e942017-10-08 19:28:20 -07004#ifndef PATH_MAX
5#define PATH_MAX 1024
Lev Walkin79f54952004-08-13 16:58:19 +00006#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 Walkina4f8e942017-10-08 19:28:20 -070044 char fname[PATH_MAX];
Lev Walkin4b102252004-08-19 13:29:18 +000045 int created = 1;
Lev Walkin93659562010-11-20 09:47:13 -080046#ifndef _WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000047 struct stat sb;
Lev Walkin4efbfb72005-02-25 14:20:30 +000048#endif
Lev Walkin4b102252004-08-19 13:29:18 +000049 FILE *fp;
Lev Walkin4604d032005-03-04 08:52:50 +000050 int ret;
Lev Walkin4b102252004-08-19 13:29:18 +000051 int fd;
52
53 /*
54 * Compute filenames.
55 */
Lev Walkina4f8e942017-10-08 19:28:20 -070056 ret = snprintf(fname, sizeof(fname), "%s%s%s", name, ext,
57 opt_tmpname ? ".XXXXXX" : "");
58 assert(ret > 0 && ret < (ssize_t)sizeof(fname));
Lev Walkin4b102252004-08-19 13:29:18 +000059
Lev Walkina4f8e942017-10-08 19:28:20 -070060 if(opt_tmpname) {
Lev Walkin4604d032005-03-04 08:52:50 +000061 /*
62 * Create temporary file.
63 */
64 fd = mkstemp(fname);
Lev Walkin93659562010-11-20 09:47:13 -080065#ifndef _WIN32
Lev Walkinebfc44d2014-10-12 19:30:12 -070066 /* fchmod() does not respect umask */
67 (void)fchmod(fd, REASONABLE_FILE_MODE);
Lev Walkin4604d032005-03-04 08:52:50 +000068#endif
69 } else {
70 /*
71 * Create specified file, or open the old one.
72 */
73 fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
74 if(fd == -1 && errno == EEXIST) {
75 fd = open(fname, O_WRONLY, DEFFILEMODE);
76 created = 0;
77 }
Lev Walkin4b102252004-08-19 13:29:18 +000078 }
79 if(fd == -1) {
80 perror(fname);
81 return NULL;
82 }
83
Lev Walkin93659562010-11-20 09:47:13 -080084#ifndef _WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000085 /*
86 * Check sanity.
87 */
88 if(fstat(fd, &sb) || !S_ISREG(sb.st_mode)) {
89 fprintf(stderr, "%s: Not a regular file\n", fname);
90 if(created) unlink(fname);
91 close(fd);
92 return NULL;
93 }
94
Lev Walkind62d7d52016-01-23 08:04:46 -080095 if(ftruncate(fd, 0) == -1) {
96 fprintf(stderr, "%s: ftruncate failed: %s\n",
97 fname, strerror(errno));
98 if(created) unlink(fname);
99 return NULL;
100 }
Lev Walkin4efbfb72005-02-25 14:20:30 +0000101#else
102 _chsize(fd, 0);
Lev Walkin93659562010-11-20 09:47:13 -0800103#endif /* _WIN32 */
Lev Walkin4b102252004-08-19 13:29:18 +0000104
105 /*
106 * Convert file descriptor into file pointer.
107 */
108 fp = fdopen(fd, "w");
109 if(fp == NULL) {
110 if(created) unlink(fname);
111 close(fd);
Lev Walkina895afb2005-10-06 10:09:34 +0000112 return NULL;
Lev Walkin4b102252004-08-19 13:29:18 +0000113 }
Lev Walkin4604d032005-03-04 08:52:50 +0000114
115 /* Return the temporary file name */
116 if(opt_tmpname) {
117 *opt_tmpname = strdup(fname);
Lev Walkina895afb2005-10-06 10:09:34 +0000118 if(*opt_tmpname) {
119 /* Successfull */
120 } else {
121 if(created) unlink(fname);
122 fclose(fp);
123 return NULL;
124 }
Lev Walkin4604d032005-03-04 08:52:50 +0000125 }
126
Lev Walkin4b102252004-08-19 13:29:18 +0000127 return fp;
128}
129
Lev Walkina4f8e942017-10-08 19:28:20 -0700130const char *
Lev Walkin79f54952004-08-13 16:58:19 +0000131a1c_basename(const char *path) {
Lev Walkina4f8e942017-10-08 19:28:20 -0700132 static char strbuf[PATH_MAX];
Lev Walkin79f54952004-08-13 16:58:19 +0000133 const char *pend;
134 const char *name;
135
136 pend = path + strlen(path);
137 if(pend == path) {
138 strcpy(strbuf, ".");
139 return strbuf;
140 }
141
142 /* Skip tailing slashes */
143 for(pend--; pend > path && *pend == '/'; pend--);
144
145 if(pend == path && *path == '/') {
146 strcpy(strbuf, "/");
147 return strbuf;
148 }
149
150 for(name = pend; name > path && name[-1] != '/'; name--);
151
Lev Walkin4b102252004-08-19 13:29:18 +0000152 if((pend - name) >= (int)sizeof(strbuf) - 1) {
Lev Walkin79f54952004-08-13 16:58:19 +0000153 errno = ENAMETOOLONG;
154 return 0;
155 }
156
157 memcpy(strbuf, name, pend - name + 1);
158 strbuf[pend - name + 1] = '\0';
159
160 return strbuf;
161}
162
163
Lev Walkina4f8e942017-10-08 19:28:20 -0700164const char *
Lev Walkin79f54952004-08-13 16:58:19 +0000165a1c_dirname(const char *path) {
Lev Walkina4f8e942017-10-08 19:28:20 -0700166 static char strbuf[PATH_MAX];
Lev Walkin79f54952004-08-13 16:58:19 +0000167 const char *pend;
168 const char *last = 0;
169 int in_slash = 0;
170
171 /* One-pass determination of the last char of the pathname */
172 for(pend = path; ; pend++) {
Lev Walkin79f54952004-08-13 16:58:19 +0000173 switch(*pend) {
174 case '\0': break;
175 case '/':
176 if(!in_slash) {
177 last = pend;
178 in_slash = 1;
179 }
180 continue;
181 default:
182 if(in_slash) in_slash = 0;
183 continue;
184 }
185 break;
186 }
Lev Walkin79f54952004-08-13 16:58:19 +0000187
188 if(last <= path) {
189 strcpy(strbuf, *path == '/' ? "/" : ".");
190 return strbuf;
191 }
192
193 if(!last) {
194 strcpy(strbuf, "/");
195 return strbuf;
196 }
197
Lev Walkin4b102252004-08-19 13:29:18 +0000198 if((last - path) >= (int)sizeof(strbuf)) {
Lev Walkin79f54952004-08-13 16:58:19 +0000199 errno = ENAMETOOLONG;
200 return 0;
201 }
202
203 memcpy(strbuf, path, last - path);
204 strbuf[last - path] = '\0';
205
206 return strbuf;
207}
208