blob: f55032c168caa81f4cb6eb40a45ca6a35eb178ee [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 Walkinebfc44d2014-10-12 19:30:12 -07004/* Normally file permissions are (DEFFILEMODE & ~umask(2)) */
Lev Walkin4b102252004-08-19 13:29:18 +00005#ifndef DEFFILEMODE /* Normally in <sys/stat.h> */
Lev Walkinebfc44d2014-10-12 19:30:12 -07006
Lev Walkin93659562010-11-20 09:47:13 -08007#ifdef _WIN32
Lev Walkine751cd82007-11-13 22:30:09 +00008#define DEFFILEMODE (S_IREAD|S_IWRITE)
Lev Walkinebfc44d2014-10-12 19:30:12 -07009#define REASONABLE_FILE_MODE DEFFILEMODE
Lev Walkin4efbfb72005-02-25 14:20:30 +000010#else
Lev Walkin4b102252004-08-19 13:29:18 +000011#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
Lev Walkinebfc44d2014-10-12 19:30:12 -070012#define REASONABLE_FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
13#endif
14#else /* !DEFFILEMODE */
15#ifdef _WIN32
16#define REASONABLE_FILE_MODE DEFFILEMODE
17#else
18#define REASONABLE_FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
Lev Walkin4b102252004-08-19 13:29:18 +000019#endif
Lev Walkin4efbfb72005-02-25 14:20:30 +000020#endif
Lev Walkin4b102252004-08-19 13:29:18 +000021
Lev Walkin50d52cf2013-03-16 08:00:57 -070022#ifdef _WIN32
23int mkstemp(char *template) {
24 char *tmpFN = _mktemp(template);
25 if(tmpFN)
26 return open(tmpFN, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
27 else
28 return -1;
29}
30#undef HAVE_MKSTEMPS
31#endif
32
Lev Walkin27fd0b62007-08-27 23:57:45 +000033#ifdef HAVE_MKSTEMPS
34#undef mkstemp
35#define mkstemp(foo) mkstemps(foo, 0)
36#endif
37
Lev Walkin4b102252004-08-19 13:29:18 +000038FILE *
Lev Walkin4604d032005-03-04 08:52:50 +000039asn1c_open_file(const char *name, const char *ext, char **opt_tmpname) {
Lev Walkina4f8e942017-10-08 19:28:20 -070040 char fname[PATH_MAX];
Lev Walkin4b102252004-08-19 13:29:18 +000041 int created = 1;
Lev Walkin93659562010-11-20 09:47:13 -080042#ifndef _WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000043 struct stat sb;
Lev Walkin4efbfb72005-02-25 14:20:30 +000044#endif
Lev Walkin4b102252004-08-19 13:29:18 +000045 FILE *fp;
Lev Walkin4604d032005-03-04 08:52:50 +000046 int ret;
Lev Walkin4b102252004-08-19 13:29:18 +000047 int fd;
48
49 /*
50 * Compute filenames.
51 */
Lev Walkina4f8e942017-10-08 19:28:20 -070052 ret = snprintf(fname, sizeof(fname), "%s%s%s", name, ext,
53 opt_tmpname ? ".XXXXXX" : "");
54 assert(ret > 0 && ret < (ssize_t)sizeof(fname));
Lev Walkin4b102252004-08-19 13:29:18 +000055
Lev Walkina4f8e942017-10-08 19:28:20 -070056 if(opt_tmpname) {
Lev Walkin4604d032005-03-04 08:52:50 +000057 /*
58 * Create temporary file.
59 */
60 fd = mkstemp(fname);
Lev Walkin93659562010-11-20 09:47:13 -080061#ifndef _WIN32
Lev Walkinebfc44d2014-10-12 19:30:12 -070062 /* fchmod() does not respect umask */
63 (void)fchmod(fd, REASONABLE_FILE_MODE);
Lev Walkin4604d032005-03-04 08:52:50 +000064#endif
65 } else {
66 /*
67 * Create specified file, or open the old one.
68 */
69 fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
70 if(fd == -1 && errno == EEXIST) {
71 fd = open(fname, O_WRONLY, DEFFILEMODE);
72 created = 0;
73 }
Lev Walkin4b102252004-08-19 13:29:18 +000074 }
75 if(fd == -1) {
76 perror(fname);
77 return NULL;
78 }
79
Lev Walkin93659562010-11-20 09:47:13 -080080#ifndef _WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000081 /*
82 * Check sanity.
83 */
84 if(fstat(fd, &sb) || !S_ISREG(sb.st_mode)) {
85 fprintf(stderr, "%s: Not a regular file\n", fname);
86 if(created) unlink(fname);
87 close(fd);
88 return NULL;
89 }
90
Lev Walkind62d7d52016-01-23 08:04:46 -080091 if(ftruncate(fd, 0) == -1) {
92 fprintf(stderr, "%s: ftruncate failed: %s\n",
93 fname, strerror(errno));
94 if(created) unlink(fname);
95 return NULL;
96 }
Lev Walkin4efbfb72005-02-25 14:20:30 +000097#else
98 _chsize(fd, 0);
Lev Walkin93659562010-11-20 09:47:13 -080099#endif /* _WIN32 */
Lev Walkin4b102252004-08-19 13:29:18 +0000100
101 /*
102 * Convert file descriptor into file pointer.
103 */
104 fp = fdopen(fd, "w");
105 if(fp == NULL) {
106 if(created) unlink(fname);
107 close(fd);
Lev Walkina895afb2005-10-06 10:09:34 +0000108 return NULL;
Lev Walkin4b102252004-08-19 13:29:18 +0000109 }
Lev Walkin4604d032005-03-04 08:52:50 +0000110
111 /* Return the temporary file name */
112 if(opt_tmpname) {
113 *opt_tmpname = strdup(fname);
Lev Walkina895afb2005-10-06 10:09:34 +0000114 if(*opt_tmpname) {
115 /* Successfull */
116 } else {
117 if(created) unlink(fname);
118 fclose(fp);
119 return NULL;
120 }
Lev Walkin4604d032005-03-04 08:52:50 +0000121 }
122
Lev Walkin4b102252004-08-19 13:29:18 +0000123 return fp;
124}
125
Lev Walkina4f8e942017-10-08 19:28:20 -0700126const char *
Lev Walkin79f54952004-08-13 16:58:19 +0000127a1c_basename(const char *path) {
Lev Walkina4f8e942017-10-08 19:28:20 -0700128 static char strbuf[PATH_MAX];
Lev Walkin79f54952004-08-13 16:58:19 +0000129 const char *pend;
130 const char *name;
131
132 pend = path + strlen(path);
133 if(pend == path) {
134 strcpy(strbuf, ".");
135 return strbuf;
136 }
137
138 /* Skip tailing slashes */
139 for(pend--; pend > path && *pend == '/'; pend--);
140
141 if(pend == path && *path == '/') {
142 strcpy(strbuf, "/");
143 return strbuf;
144 }
145
146 for(name = pend; name > path && name[-1] != '/'; name--);
147
Lev Walkin4b102252004-08-19 13:29:18 +0000148 if((pend - name) >= (int)sizeof(strbuf) - 1) {
Lev Walkin79f54952004-08-13 16:58:19 +0000149 errno = ENAMETOOLONG;
150 return 0;
151 }
152
153 memcpy(strbuf, name, pend - name + 1);
154 strbuf[pend - name + 1] = '\0';
155
156 return strbuf;
157}
158
159
Lev Walkina4f8e942017-10-08 19:28:20 -0700160const char *
Lev Walkin79f54952004-08-13 16:58:19 +0000161a1c_dirname(const char *path) {
Lev Walkina4f8e942017-10-08 19:28:20 -0700162 static char strbuf[PATH_MAX];
Lev Walkin79f54952004-08-13 16:58:19 +0000163 const char *pend;
164 const char *last = 0;
165 int in_slash = 0;
166
167 /* One-pass determination of the last char of the pathname */
168 for(pend = path; ; pend++) {
Lev Walkin79f54952004-08-13 16:58:19 +0000169 switch(*pend) {
170 case '\0': break;
171 case '/':
172 if(!in_slash) {
173 last = pend;
174 in_slash = 1;
175 }
176 continue;
177 default:
178 if(in_slash) in_slash = 0;
179 continue;
180 }
181 break;
182 }
Lev Walkin79f54952004-08-13 16:58:19 +0000183
184 if(last <= path) {
185 strcpy(strbuf, *path == '/' ? "/" : ".");
186 return strbuf;
187 }
188
189 if(!last) {
190 strcpy(strbuf, "/");
191 return strbuf;
192 }
193
Lev Walkin4b102252004-08-19 13:29:18 +0000194 if((last - path) >= (int)sizeof(strbuf)) {
Lev Walkin79f54952004-08-13 16:58:19 +0000195 errno = ENAMETOOLONG;
196 return 0;
197 }
198
199 memcpy(strbuf, path, last - path);
200 strbuf[last - path] = '\0';
201
202 return strbuf;
203}
204