blob: 2a80251a3208fa376495f8868f7c4c6aabcd5f6f [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);
83 }
Lev Walkin4604d032005-03-04 08:52:50 +000084
85 /* Return the temporary file name */
86 if(opt_tmpname) {
87 *opt_tmpname = strdup(fname);
88 assert(*opt_tmpname);
89 }
90
Lev Walkin4b102252004-08-19 13:29:18 +000091 return fp;
92}
93
94
Lev Walkin79f54952004-08-13 16:58:19 +000095char *
96a1c_basename(const char *path) {
97 static char strbuf[MAXPATHLEN];
98 const char *pend;
99 const char *name;
100
101 pend = path + strlen(path);
102 if(pend == path) {
103 strcpy(strbuf, ".");
104 return strbuf;
105 }
106
107 /* Skip tailing slashes */
108 for(pend--; pend > path && *pend == '/'; pend--);
109
110 if(pend == path && *path == '/') {
111 strcpy(strbuf, "/");
112 return strbuf;
113 }
114
115 for(name = pend; name > path && name[-1] != '/'; name--);
116
Lev Walkin4b102252004-08-19 13:29:18 +0000117 if((pend - name) >= (int)sizeof(strbuf) - 1) {
Lev Walkin79f54952004-08-13 16:58:19 +0000118 errno = ENAMETOOLONG;
119 return 0;
120 }
121
122 memcpy(strbuf, name, pend - name + 1);
123 strbuf[pend - name + 1] = '\0';
124
125 return strbuf;
126}
127
128
129char *
130a1c_dirname(const char *path) {
131 static char strbuf[MAXPATHLEN];
132 const char *pend;
133 const char *last = 0;
134 int in_slash = 0;
135
136 /* One-pass determination of the last char of the pathname */
137 for(pend = path; ; pend++) {
Lev Walkin79f54952004-08-13 16:58:19 +0000138 switch(*pend) {
139 case '\0': break;
140 case '/':
141 if(!in_slash) {
142 last = pend;
143 in_slash = 1;
144 }
145 continue;
146 default:
147 if(in_slash) in_slash = 0;
148 continue;
149 }
150 break;
151 }
Lev Walkin79f54952004-08-13 16:58:19 +0000152
153 if(last <= path) {
154 strcpy(strbuf, *path == '/' ? "/" : ".");
155 return strbuf;
156 }
157
158 if(!last) {
159 strcpy(strbuf, "/");
160 return strbuf;
161 }
162
Lev Walkin4b102252004-08-19 13:29:18 +0000163 if((last - path) >= (int)sizeof(strbuf)) {
Lev Walkin79f54952004-08-13 16:58:19 +0000164 errno = ENAMETOOLONG;
165 return 0;
166 }
167
168 memcpy(strbuf, path, last - path);
169 strbuf[last - path] = '\0';
170
171 return strbuf;
172}
173