NativeEnumerated.c vars NULL init and check
[com/asn1c.git] / libasn1compiler / asn1c_compat.c
1 #include "asn1c_internal.h"
2 #include "asn1c_compat.h"
3
4 /* Normally file permissions are (DEFFILEMODE & ~umask(2)) */
5 #ifndef DEFFILEMODE     /* Normally in <sys/stat.h> */
6
7 #ifdef  _WIN32
8 #define DEFFILEMODE     (S_IREAD|S_IWRITE)
9 #define REASONABLE_FILE_MODE    DEFFILEMODE
10 #else
11 #define DEFFILEMODE     (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
12 #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)
19 #endif
20 #endif
21
22 #ifdef _WIN32
23 int 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
33 #ifdef  HAVE_MKSTEMPS
34 #undef  mkstemp
35 #define mkstemp(foo)    mkstemps(foo, 0)
36 #endif
37
38 FILE *
39 asn1c_open_file(const char *destdir, const char *name, const char *ext,
40                 char **opt_tmpname) {
41     char fname[PATH_MAX];
42         int created = 1;
43 #ifndef _WIN32
44         struct stat sb;
45 #endif
46         FILE *fp;
47         int ret;
48         int fd;
49
50         /*
51          * Compute filenames.
52          */
53     ret = snprintf(fname, sizeof(fname), "%s%s%s%s", destdir ? destdir : "",
54                    name, ext, opt_tmpname ? ".XXXXXX" : "");
55     assert(ret > 0 && ret < (ssize_t)sizeof(fname));
56
57     if(opt_tmpname) {
58                 /*
59                  * Create temporary file.
60                  */
61                 fd = mkstemp(fname);
62 #ifndef _WIN32
63         if(fd != -1) {
64             /* fchmod() does not respect umask */
65             (void)fchmod(fd, REASONABLE_FILE_MODE);
66         }
67 #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                 }
77         }
78         if(fd == -1) {
79         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         }
87         }
88
89 #ifndef _WIN32
90         /*
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
100         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     }
106 #else
107         _chsize(fd, 0);
108 #endif  /* _WIN32 */
109
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);
117                 return NULL;
118         }
119
120         /* Return the temporary file name */
121         if(opt_tmpname) {
122                 *opt_tmpname = strdup(fname);
123                 if(*opt_tmpname) {
124                         /* Successfull */
125                 } else {
126                         if(created) unlink(fname);
127                         fclose(fp);
128                         return NULL;
129                 }
130         }
131
132         return fp;
133 }
134
135 const char *
136 a1c_basename(const char *path, const char *destdir) {
137         static char strbuf[PATH_MAX];
138         const char *pend;
139         const char *name;
140         char *sbuf = strbuf;
141
142         if(destdir) {
143                 strncpy(strbuf, destdir, PATH_MAX - 1);
144                 strbuf[PATH_MAX - 1] = '\0';
145                 sbuf = strbuf + strlen(strbuf);
146         }
147         pend = path + strlen(path);
148         if(pend == path) {
149                 strcpy(sbuf, ".");
150                 return strbuf;
151         }
152
153         /* Skip tailing slashes */
154         for(pend--; pend > path && *pend == '/'; pend--);
155
156         if(pend == path && *path == '/') {
157                 strcpy(sbuf, "/");
158                 return strbuf;
159         }
160
161         for(name = pend; name > path && name[-1] != '/'; name--);
162
163         if((pend - name) >= (int)sizeof(strbuf) - 1) {
164                 errno = ENAMETOOLONG;
165                 return 0;
166         }
167
168         memcpy(sbuf, name, pend - name + 1);
169         sbuf[pend - name + 1] = '\0';
170
171         return strbuf;
172 }
173
174
175 const char *
176 a1c_dirname(const char *path) {
177         static char strbuf[PATH_MAX];
178         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++) {
184                 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         }
198
199         if(last <= path) {
200                 strcpy(strbuf, *path == '/' ? "/" : ".");
201                 return strbuf;
202         }
203
204         if(!last) {
205                 strcpy(strbuf, "/");
206                 return strbuf;
207         }
208
209         if((last - path) >= (int)sizeof(strbuf)) {
210                 errno = ENAMETOOLONG;
211                 return 0;
212         }
213
214         memcpy(strbuf, path, last - path);
215         strbuf[last - path] = '\0';
216
217         return strbuf;
218 }
219