blob: 6c47d02cf65010499d02ceeb4136f421bc217b7f [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 Walkinda672c42017-11-18 11:57:39 -080039asn1c_open_file(const char *destdir, const char *name, const char *ext,
40 char **opt_tmpname) {
41 char fname[PATH_MAX];
Lev Walkin4b102252004-08-19 13:29:18 +000042 int created = 1;
Lev Walkin93659562010-11-20 09:47:13 -080043#ifndef _WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000044 struct stat sb;
Lev Walkin4efbfb72005-02-25 14:20:30 +000045#endif
Lev Walkin4b102252004-08-19 13:29:18 +000046 FILE *fp;
Lev Walkin4604d032005-03-04 08:52:50 +000047 int ret;
Lev Walkin4b102252004-08-19 13:29:18 +000048 int fd;
49
50 /*
51 * Compute filenames.
52 */
Lev Walkinda672c42017-11-18 11:57:39 -080053 ret = snprintf(fname, sizeof(fname), "%s%s%s%s", destdir ? destdir : "",
54 name, ext, opt_tmpname ? ".XXXXXX" : "");
Lev Walkina4f8e942017-10-08 19:28:20 -070055 assert(ret > 0 && ret < (ssize_t)sizeof(fname));
Lev Walkin4b102252004-08-19 13:29:18 +000056
Lev Walkina4f8e942017-10-08 19:28:20 -070057 if(opt_tmpname) {
Lev Walkin4604d032005-03-04 08:52:50 +000058 /*
59 * Create temporary file.
60 */
61 fd = mkstemp(fname);
Lev Walkin93659562010-11-20 09:47:13 -080062#ifndef _WIN32
Lev Walkinda672c42017-11-18 11:57:39 -080063 if(fd != -1) {
64 /* fchmod() does not respect umask */
65 (void)fchmod(fd, REASONABLE_FILE_MODE);
66 }
Lev Walkin4604d032005-03-04 08:52:50 +000067#endif
68 } else {
69 /*
70 * Create specified file, or open the old one.
71 */
72 fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
73 if(fd == -1 && errno == EEXIST) {
74 fd = open(fname, O_WRONLY, DEFFILEMODE);
75 created = 0;
76 }
Lev Walkin4b102252004-08-19 13:29:18 +000077 }
78 if(fd == -1) {
Lev Walkinda672c42017-11-18 11:57:39 -080079 struct stat st;
80 if(destdir && stat(destdir, &st) == -1) {
81 fprintf(stderr, "%s: No such directory\n", destdir);
82 return NULL;
83 } else {
84 perror(fname);
85 return NULL;
86 }
Lev Walkin4b102252004-08-19 13:29:18 +000087 }
88
Lev Walkin93659562010-11-20 09:47:13 -080089#ifndef _WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000090 /*
91 * Check sanity.
92 */
93 if(fstat(fd, &sb) || !S_ISREG(sb.st_mode)) {
94 fprintf(stderr, "%s: Not a regular file\n", fname);
95 if(created) unlink(fname);
96 close(fd);
97 return NULL;
98 }
99
Lev Walkind62d7d52016-01-23 08:04:46 -0800100 if(ftruncate(fd, 0) == -1) {
101 fprintf(stderr, "%s: ftruncate failed: %s\n",
102 fname, strerror(errno));
103 if(created) unlink(fname);
104 return NULL;
105 }
Lev Walkin4efbfb72005-02-25 14:20:30 +0000106#else
107 _chsize(fd, 0);
Lev Walkin93659562010-11-20 09:47:13 -0800108#endif /* _WIN32 */
Lev Walkin4b102252004-08-19 13:29:18 +0000109
110 /*
111 * Convert file descriptor into file pointer.
112 */
113 fp = fdopen(fd, "w");
114 if(fp == NULL) {
115 if(created) unlink(fname);
116 close(fd);
Lev Walkina895afb2005-10-06 10:09:34 +0000117 return NULL;
Lev Walkin4b102252004-08-19 13:29:18 +0000118 }
Lev Walkin4604d032005-03-04 08:52:50 +0000119
120 /* Return the temporary file name */
121 if(opt_tmpname) {
122 *opt_tmpname = strdup(fname);
Lev Walkina895afb2005-10-06 10:09:34 +0000123 if(*opt_tmpname) {
124 /* Successfull */
125 } else {
126 if(created) unlink(fname);
127 fclose(fp);
128 return NULL;
129 }
Lev Walkin4604d032005-03-04 08:52:50 +0000130 }
131
Lev Walkin4b102252004-08-19 13:29:18 +0000132 return fp;
133}
134
Lev Walkina4f8e942017-10-08 19:28:20 -0700135const char *
Jon Ringle6431b1c2017-11-15 01:22:02 -0500136a1c_basename(const char *path, const char *destdir) {
Lev Walkina4f8e942017-10-08 19:28:20 -0700137 static char strbuf[PATH_MAX];
Lev Walkin79f54952004-08-13 16:58:19 +0000138 const char *pend;
139 const char *name;
Jon Ringle6431b1c2017-11-15 01:22:02 -0500140 char *sbuf = strbuf;
Lev Walkin79f54952004-08-13 16:58:19 +0000141
Jon Ringle6431b1c2017-11-15 01:22:02 -0500142 if(destdir) {
143 strncpy(strbuf, destdir, PATH_MAX - 1);
144 strbuf[PATH_MAX - 1] = '\0';
145 sbuf = strbuf + strlen(strbuf);
146 }
Lev Walkin79f54952004-08-13 16:58:19 +0000147 pend = path + strlen(path);
148 if(pend == path) {
Jon Ringle6431b1c2017-11-15 01:22:02 -0500149 strcpy(sbuf, ".");
Lev Walkin79f54952004-08-13 16:58:19 +0000150 return strbuf;
151 }
152
153 /* Skip tailing slashes */
154 for(pend--; pend > path && *pend == '/'; pend--);
155
156 if(pend == path && *path == '/') {
Jon Ringle6431b1c2017-11-15 01:22:02 -0500157 strcpy(sbuf, "/");
Lev Walkin79f54952004-08-13 16:58:19 +0000158 return strbuf;
159 }
160
161 for(name = pend; name > path && name[-1] != '/'; name--);
162
Lev Walkin4b102252004-08-19 13:29:18 +0000163 if((pend - name) >= (int)sizeof(strbuf) - 1) {
Lev Walkin79f54952004-08-13 16:58:19 +0000164 errno = ENAMETOOLONG;
165 return 0;
166 }
167
Jon Ringle6431b1c2017-11-15 01:22:02 -0500168 memcpy(sbuf, name, pend - name + 1);
169 sbuf[pend - name + 1] = '\0';
Lev Walkin79f54952004-08-13 16:58:19 +0000170
171 return strbuf;
172}
173
174
Lev Walkina4f8e942017-10-08 19:28:20 -0700175const char *
Lev Walkin79f54952004-08-13 16:58:19 +0000176a1c_dirname(const char *path) {
Lev Walkina4f8e942017-10-08 19:28:20 -0700177 static char strbuf[PATH_MAX];
Lev Walkin79f54952004-08-13 16:58:19 +0000178 const char *pend;
179 const char *last = 0;
180 int in_slash = 0;
181
182 /* One-pass determination of the last char of the pathname */
183 for(pend = path; ; pend++) {
Lev Walkin79f54952004-08-13 16:58:19 +0000184 switch(*pend) {
185 case '\0': break;
186 case '/':
187 if(!in_slash) {
188 last = pend;
189 in_slash = 1;
190 }
191 continue;
192 default:
193 if(in_slash) in_slash = 0;
194 continue;
195 }
196 break;
197 }
Lev Walkin79f54952004-08-13 16:58:19 +0000198
199 if(last <= path) {
200 strcpy(strbuf, *path == '/' ? "/" : ".");
201 return strbuf;
202 }
203
204 if(!last) {
205 strcpy(strbuf, "/");
206 return strbuf;
207 }
208
Lev Walkin4b102252004-08-19 13:29:18 +0000209 if((last - path) >= (int)sizeof(strbuf)) {
Lev Walkin79f54952004-08-13 16:58:19 +0000210 errno = ENAMETOOLONG;
211 return 0;
212 }
213
214 memcpy(strbuf, path, last - path);
215 strbuf[last - path] = '\0';
216
217 return strbuf;
218}
219