blob: 17dd906896190f7a53d29a8892bf32965e85fda0 [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 Walkin4efbfb72005-02-25 14:20:30 +00009#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 Walkin27fd0b62007-08-27 23:57:45 +000016#ifdef HAVE_MKSTEMPS
17#undef mkstemp
18#define mkstemp(foo) mkstemps(foo, 0)
19#endif
20
Lev Walkin4b102252004-08-19 13:29:18 +000021FILE *
Lev Walkin4604d032005-03-04 08:52:50 +000022asn1c_open_file(const char *name, const char *ext, char **opt_tmpname) {
Lev Walkin4b102252004-08-19 13:29:18 +000023 int created = 1;
Lev Walkin4efbfb72005-02-25 14:20:30 +000024#ifndef WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000025 struct stat sb;
Lev Walkin4efbfb72005-02-25 14:20:30 +000026#endif
Lev Walkin4b102252004-08-19 13:29:18 +000027 char *fname;
Lev Walkin4efbfb72005-02-25 14:20:30 +000028 size_t len;
Lev Walkin4b102252004-08-19 13:29:18 +000029 FILE *fp;
Lev Walkin4604d032005-03-04 08:52:50 +000030 int ret;
Lev Walkin4b102252004-08-19 13:29:18 +000031 int fd;
32
33 /*
34 * Compute filenames.
35 */
Lev Walkin4604d032005-03-04 08:52:50 +000036 len = strlen(name) + strlen(ext) + sizeof(".XXXXXX");
Lev Walkin4b102252004-08-19 13:29:18 +000037 fname = alloca(len);
Lev Walkin4604d032005-03-04 08:52:50 +000038 ret = snprintf(fname, len, "%s%s%s", name, ext,
39 opt_tmpname ? ".XXXXXX" : "");
Lev Walkinc46b7cb2006-08-18 02:27:55 +000040 assert(ret > 0 && ret < (ssize_t)len);
Lev Walkin4b102252004-08-19 13:29:18 +000041
Lev Walkin4604d032005-03-04 08:52:50 +000042 if(opt_tmpname) {
43 /*
44 * Create temporary file.
45 */
46 fd = mkstemp(fname);
47#ifndef WIN32
48 (void)fchmod(fd, DEFFILEMODE);
49#endif
50 } else {
51 /*
52 * Create specified file, or open the old one.
53 */
54 fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
55 if(fd == -1 && errno == EEXIST) {
56 fd = open(fname, O_WRONLY, DEFFILEMODE);
57 created = 0;
58 }
Lev Walkin4b102252004-08-19 13:29:18 +000059 }
60 if(fd == -1) {
61 perror(fname);
62 return NULL;
63 }
64
Lev Walkin4efbfb72005-02-25 14:20:30 +000065#ifndef WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000066 /*
67 * Check sanity.
68 */
69 if(fstat(fd, &sb) || !S_ISREG(sb.st_mode)) {
70 fprintf(stderr, "%s: Not a regular file\n", fname);
71 if(created) unlink(fname);
72 close(fd);
73 return NULL;
74 }
75
76 (void)ftruncate(fd, 0);
Lev Walkin4efbfb72005-02-25 14:20:30 +000077#else
78 _chsize(fd, 0);
79#endif /* WIN32 */
Lev Walkin4b102252004-08-19 13:29:18 +000080
81 /*
82 * Convert file descriptor into file pointer.
83 */
84 fp = fdopen(fd, "w");
85 if(fp == NULL) {
86 if(created) unlink(fname);
87 close(fd);
Lev Walkina895afb2005-10-06 10:09:34 +000088 return NULL;
Lev Walkin4b102252004-08-19 13:29:18 +000089 }
Lev Walkin4604d032005-03-04 08:52:50 +000090
91 /* Return the temporary file name */
92 if(opt_tmpname) {
93 *opt_tmpname = strdup(fname);
Lev Walkina895afb2005-10-06 10:09:34 +000094 if(*opt_tmpname) {
95 /* Successfull */
96 } else {
97 if(created) unlink(fname);
98 fclose(fp);
99 return NULL;
100 }
Lev Walkin4604d032005-03-04 08:52:50 +0000101 }
102
Lev Walkin4b102252004-08-19 13:29:18 +0000103 return fp;
104}
105
106
Lev Walkin79f54952004-08-13 16:58:19 +0000107char *
108a1c_basename(const char *path) {
109 static char strbuf[MAXPATHLEN];
110 const char *pend;
111 const char *name;
112
113 pend = path + strlen(path);
114 if(pend == path) {
115 strcpy(strbuf, ".");
116 return strbuf;
117 }
118
119 /* Skip tailing slashes */
120 for(pend--; pend > path && *pend == '/'; pend--);
121
122 if(pend == path && *path == '/') {
123 strcpy(strbuf, "/");
124 return strbuf;
125 }
126
127 for(name = pend; name > path && name[-1] != '/'; name--);
128
Lev Walkin4b102252004-08-19 13:29:18 +0000129 if((pend - name) >= (int)sizeof(strbuf) - 1) {
Lev Walkin79f54952004-08-13 16:58:19 +0000130 errno = ENAMETOOLONG;
131 return 0;
132 }
133
134 memcpy(strbuf, name, pend - name + 1);
135 strbuf[pend - name + 1] = '\0';
136
137 return strbuf;
138}
139
140
141char *
142a1c_dirname(const char *path) {
143 static char strbuf[MAXPATHLEN];
144 const char *pend;
145 const char *last = 0;
146 int in_slash = 0;
147
148 /* One-pass determination of the last char of the pathname */
149 for(pend = path; ; pend++) {
Lev Walkin79f54952004-08-13 16:58:19 +0000150 switch(*pend) {
151 case '\0': break;
152 case '/':
153 if(!in_slash) {
154 last = pend;
155 in_slash = 1;
156 }
157 continue;
158 default:
159 if(in_slash) in_slash = 0;
160 continue;
161 }
162 break;
163 }
Lev Walkin79f54952004-08-13 16:58:19 +0000164
165 if(last <= path) {
166 strcpy(strbuf, *path == '/' ? "/" : ".");
167 return strbuf;
168 }
169
170 if(!last) {
171 strcpy(strbuf, "/");
172 return strbuf;
173 }
174
Lev Walkin4b102252004-08-19 13:29:18 +0000175 if((last - path) >= (int)sizeof(strbuf)) {
Lev Walkin79f54952004-08-13 16:58:19 +0000176 errno = ENAMETOOLONG;
177 return 0;
178 }
179
180 memcpy(strbuf, path, last - path);
181 strbuf[last - path] = '\0';
182
183 return strbuf;
184}
185