blob: 8cb78cde679a821539423eaea8aae3bfdec51a7a [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 Walkin4b102252004-08-19 13:29:18 +00008#ifndef DEFFILEMODE /* Normally in <sys/stat.h> */
Lev Walkin93659562010-11-20 09:47:13 -08009#ifdef _WIN32
Lev Walkine751cd82007-11-13 22:30:09 +000010#define DEFFILEMODE (S_IREAD|S_IWRITE)
Lev Walkin4efbfb72005-02-25 14:20:30 +000011#else
Lev Walkin4b102252004-08-19 13:29:18 +000012#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
13#endif
Lev Walkin4efbfb72005-02-25 14:20:30 +000014#endif
Lev Walkin4b102252004-08-19 13:29:18 +000015
Lev Walkin50d52cf2013-03-16 08:00:57 -070016#ifdef _WIN32
17int mkstemp(char *template) {
18 char *tmpFN = _mktemp(template);
19 if(tmpFN)
20 return open(tmpFN, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
21 else
22 return -1;
23}
24#undef HAVE_MKSTEMPS
25#endif
26
Lev Walkin27fd0b62007-08-27 23:57:45 +000027#ifdef HAVE_MKSTEMPS
28#undef mkstemp
29#define mkstemp(foo) mkstemps(foo, 0)
30#endif
31
Lev Walkin4b102252004-08-19 13:29:18 +000032FILE *
Lev Walkin4604d032005-03-04 08:52:50 +000033asn1c_open_file(const char *name, const char *ext, char **opt_tmpname) {
Lev Walkin4b102252004-08-19 13:29:18 +000034 int created = 1;
Lev Walkin93659562010-11-20 09:47:13 -080035#ifndef _WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000036 struct stat sb;
Lev Walkin4efbfb72005-02-25 14:20:30 +000037#endif
Lev Walkin4b102252004-08-19 13:29:18 +000038 char *fname;
Lev Walkin4efbfb72005-02-25 14:20:30 +000039 size_t len;
Lev Walkin4b102252004-08-19 13:29:18 +000040 FILE *fp;
Lev Walkin4604d032005-03-04 08:52:50 +000041 int ret;
Lev Walkin4b102252004-08-19 13:29:18 +000042 int fd;
43
44 /*
45 * Compute filenames.
46 */
Lev Walkin4604d032005-03-04 08:52:50 +000047 len = strlen(name) + strlen(ext) + sizeof(".XXXXXX");
Lev Walkin4b102252004-08-19 13:29:18 +000048 fname = alloca(len);
Lev Walkin4604d032005-03-04 08:52:50 +000049 ret = snprintf(fname, len, "%s%s%s", name, ext,
50 opt_tmpname ? ".XXXXXX" : "");
Lev Walkinc46b7cb2006-08-18 02:27:55 +000051 assert(ret > 0 && ret < (ssize_t)len);
Lev Walkin4b102252004-08-19 13:29:18 +000052
Lev Walkin4604d032005-03-04 08:52:50 +000053 if(opt_tmpname) {
54 /*
55 * Create temporary file.
56 */
57 fd = mkstemp(fname);
Lev Walkin93659562010-11-20 09:47:13 -080058#ifndef _WIN32
Lev Walkin4604d032005-03-04 08:52:50 +000059 (void)fchmod(fd, DEFFILEMODE);
60#endif
61 } else {
62 /*
63 * Create specified file, or open the old one.
64 */
65 fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
66 if(fd == -1 && errno == EEXIST) {
67 fd = open(fname, O_WRONLY, DEFFILEMODE);
68 created = 0;
69 }
Lev Walkin4b102252004-08-19 13:29:18 +000070 }
71 if(fd == -1) {
72 perror(fname);
73 return NULL;
74 }
75
Lev Walkin93659562010-11-20 09:47:13 -080076#ifndef _WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000077 /*
78 * Check sanity.
79 */
80 if(fstat(fd, &sb) || !S_ISREG(sb.st_mode)) {
81 fprintf(stderr, "%s: Not a regular file\n", fname);
82 if(created) unlink(fname);
83 close(fd);
84 return NULL;
85 }
86
87 (void)ftruncate(fd, 0);
Lev Walkin4efbfb72005-02-25 14:20:30 +000088#else
89 _chsize(fd, 0);
Lev Walkin93659562010-11-20 09:47:13 -080090#endif /* _WIN32 */
Lev Walkin4b102252004-08-19 13:29:18 +000091
92 /*
93 * Convert file descriptor into file pointer.
94 */
95 fp = fdopen(fd, "w");
96 if(fp == NULL) {
97 if(created) unlink(fname);
98 close(fd);
Lev Walkina895afb2005-10-06 10:09:34 +000099 return NULL;
Lev Walkin4b102252004-08-19 13:29:18 +0000100 }
Lev Walkin4604d032005-03-04 08:52:50 +0000101
102 /* Return the temporary file name */
103 if(opt_tmpname) {
104 *opt_tmpname = strdup(fname);
Lev Walkina895afb2005-10-06 10:09:34 +0000105 if(*opt_tmpname) {
106 /* Successfull */
107 } else {
108 if(created) unlink(fname);
109 fclose(fp);
110 return NULL;
111 }
Lev Walkin4604d032005-03-04 08:52:50 +0000112 }
113
Lev Walkin4b102252004-08-19 13:29:18 +0000114 return fp;
115}
116
117
Lev Walkin79f54952004-08-13 16:58:19 +0000118char *
119a1c_basename(const char *path) {
120 static char strbuf[MAXPATHLEN];
121 const char *pend;
122 const char *name;
123
124 pend = path + strlen(path);
125 if(pend == path) {
126 strcpy(strbuf, ".");
127 return strbuf;
128 }
129
130 /* Skip tailing slashes */
131 for(pend--; pend > path && *pend == '/'; pend--);
132
133 if(pend == path && *path == '/') {
134 strcpy(strbuf, "/");
135 return strbuf;
136 }
137
138 for(name = pend; name > path && name[-1] != '/'; name--);
139
Lev Walkin4b102252004-08-19 13:29:18 +0000140 if((pend - name) >= (int)sizeof(strbuf) - 1) {
Lev Walkin79f54952004-08-13 16:58:19 +0000141 errno = ENAMETOOLONG;
142 return 0;
143 }
144
145 memcpy(strbuf, name, pend - name + 1);
146 strbuf[pend - name + 1] = '\0';
147
148 return strbuf;
149}
150
151
152char *
153a1c_dirname(const char *path) {
154 static char strbuf[MAXPATHLEN];
155 const char *pend;
156 const char *last = 0;
157 int in_slash = 0;
158
159 /* One-pass determination of the last char of the pathname */
160 for(pend = path; ; pend++) {
Lev Walkin79f54952004-08-13 16:58:19 +0000161 switch(*pend) {
162 case '\0': break;
163 case '/':
164 if(!in_slash) {
165 last = pend;
166 in_slash = 1;
167 }
168 continue;
169 default:
170 if(in_slash) in_slash = 0;
171 continue;
172 }
173 break;
174 }
Lev Walkin79f54952004-08-13 16:58:19 +0000175
176 if(last <= path) {
177 strcpy(strbuf, *path == '/' ? "/" : ".");
178 return strbuf;
179 }
180
181 if(!last) {
182 strcpy(strbuf, "/");
183 return strbuf;
184 }
185
Lev Walkin4b102252004-08-19 13:29:18 +0000186 if((last - path) >= (int)sizeof(strbuf)) {
Lev Walkin79f54952004-08-13 16:58:19 +0000187 errno = ENAMETOOLONG;
188 return 0;
189 }
190
191 memcpy(strbuf, path, last - path);
192 strbuf[last - path] = '\0';
193
194 return strbuf;
195}
196