blob: b393d6d2a45598e951cc63a6f0386f349147bcce [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
10#define DEFFILEMODE 0
11#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
16FILE *
Lev Walkin4604d032005-03-04 08:52:50 +000017asn1c_open_file(const char *name, const char *ext, char **opt_tmpname) {
Lev Walkin4b102252004-08-19 13:29:18 +000018 int created = 1;
Lev Walkin4efbfb72005-02-25 14:20:30 +000019#ifndef WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000020 struct stat sb;
Lev Walkin4efbfb72005-02-25 14:20:30 +000021#endif
Lev Walkin4b102252004-08-19 13:29:18 +000022 char *fname;
Lev Walkin4efbfb72005-02-25 14:20:30 +000023 size_t len;
Lev Walkin4b102252004-08-19 13:29:18 +000024 FILE *fp;
Lev Walkin4604d032005-03-04 08:52:50 +000025 int ret;
Lev Walkin4b102252004-08-19 13:29:18 +000026 int fd;
27
28 /*
29 * Compute filenames.
30 */
Lev Walkin4604d032005-03-04 08:52:50 +000031 len = strlen(name) + strlen(ext) + sizeof(".XXXXXX");
Lev Walkin4b102252004-08-19 13:29:18 +000032 fname = alloca(len);
Lev Walkin4604d032005-03-04 08:52:50 +000033 ret = snprintf(fname, len, "%s%s%s", name, ext,
34 opt_tmpname ? ".XXXXXX" : "");
35 assert(ret > 0 && ret < len);
Lev Walkin4b102252004-08-19 13:29:18 +000036
Lev Walkin4604d032005-03-04 08:52:50 +000037 if(opt_tmpname) {
38 /*
39 * Create temporary file.
40 */
41 fd = mkstemp(fname);
42#ifndef WIN32
43 (void)fchmod(fd, DEFFILEMODE);
44#endif
45 } else {
46 /*
47 * Create specified file, or open the old one.
48 */
49 fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
50 if(fd == -1 && errno == EEXIST) {
51 fd = open(fname, O_WRONLY, DEFFILEMODE);
52 created = 0;
53 }
Lev Walkin4b102252004-08-19 13:29:18 +000054 }
55 if(fd == -1) {
56 perror(fname);
57 return NULL;
58 }
59
Lev Walkin4efbfb72005-02-25 14:20:30 +000060#ifndef WIN32
Lev Walkin4b102252004-08-19 13:29:18 +000061 /*
62 * Check sanity.
63 */
64 if(fstat(fd, &sb) || !S_ISREG(sb.st_mode)) {
65 fprintf(stderr, "%s: Not a regular file\n", fname);
66 if(created) unlink(fname);
67 close(fd);
68 return NULL;
69 }
70
71 (void)ftruncate(fd, 0);
Lev Walkin4efbfb72005-02-25 14:20:30 +000072#else
73 _chsize(fd, 0);
74#endif /* WIN32 */
Lev Walkin4b102252004-08-19 13:29:18 +000075
76 /*
77 * Convert file descriptor into file pointer.
78 */
79 fp = fdopen(fd, "w");
80 if(fp == NULL) {
81 if(created) unlink(fname);
82 close(fd);
Lev Walkina895afb2005-10-06 10:09:34 +000083 return NULL;
Lev Walkin4b102252004-08-19 13:29:18 +000084 }
Lev Walkin4604d032005-03-04 08:52:50 +000085
86 /* Return the temporary file name */
87 if(opt_tmpname) {
88 *opt_tmpname = strdup(fname);
Lev Walkina895afb2005-10-06 10:09:34 +000089 if(*opt_tmpname) {
90 /* Successfull */
91 } else {
92 if(created) unlink(fname);
93 fclose(fp);
94 return NULL;
95 }
Lev Walkin4604d032005-03-04 08:52:50 +000096 }
97
Lev Walkin4b102252004-08-19 13:29:18 +000098 return fp;
99}
100
101
Lev Walkin79f54952004-08-13 16:58:19 +0000102char *
103a1c_basename(const char *path) {
104 static char strbuf[MAXPATHLEN];
105 const char *pend;
106 const char *name;
107
108 pend = path + strlen(path);
109 if(pend == path) {
110 strcpy(strbuf, ".");
111 return strbuf;
112 }
113
114 /* Skip tailing slashes */
115 for(pend--; pend > path && *pend == '/'; pend--);
116
117 if(pend == path && *path == '/') {
118 strcpy(strbuf, "/");
119 return strbuf;
120 }
121
122 for(name = pend; name > path && name[-1] != '/'; name--);
123
Lev Walkin4b102252004-08-19 13:29:18 +0000124 if((pend - name) >= (int)sizeof(strbuf) - 1) {
Lev Walkin79f54952004-08-13 16:58:19 +0000125 errno = ENAMETOOLONG;
126 return 0;
127 }
128
129 memcpy(strbuf, name, pend - name + 1);
130 strbuf[pend - name + 1] = '\0';
131
132 return strbuf;
133}
134
135
136char *
137a1c_dirname(const char *path) {
138 static char strbuf[MAXPATHLEN];
139 const char *pend;
140 const char *last = 0;
141 int in_slash = 0;
142
143 /* One-pass determination of the last char of the pathname */
144 for(pend = path; ; pend++) {
Lev Walkin79f54952004-08-13 16:58:19 +0000145 switch(*pend) {
146 case '\0': break;
147 case '/':
148 if(!in_slash) {
149 last = pend;
150 in_slash = 1;
151 }
152 continue;
153 default:
154 if(in_slash) in_slash = 0;
155 continue;
156 }
157 break;
158 }
Lev Walkin79f54952004-08-13 16:58:19 +0000159
160 if(last <= path) {
161 strcpy(strbuf, *path == '/' ? "/" : ".");
162 return strbuf;
163 }
164
165 if(!last) {
166 strcpy(strbuf, "/");
167 return strbuf;
168 }
169
Lev Walkin4b102252004-08-19 13:29:18 +0000170 if((last - path) >= (int)sizeof(strbuf)) {
Lev Walkin79f54952004-08-13 16:58:19 +0000171 errno = ENAMETOOLONG;
172 return 0;
173 }
174
175 memcpy(strbuf, path, last - path);
176 strbuf[last - path] = '\0';
177
178 return strbuf;
179}
180