xref: /netbsd-src/external/mit/expat/dist/xmlwf/readfilemap.c (revision 7c192b2a5e1093666e67801684f930ef49b3b363)
1 /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
2    See the file COPYING for copying permission.
3 */
4 
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 
11 /* Functions close(2) and read(2) */
12 #if !defined(_WIN32) && !defined(_WIN64)
13 # include <unistd.h>
14 #endif
15 
16 #ifndef S_ISREG
17 #ifndef S_IFREG
18 #define S_IFREG _S_IFREG
19 #endif
20 #ifndef S_IFMT
21 #define S_IFMT _S_IFMT
22 #endif
23 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
24 #endif /* not S_ISREG */
25 
26 #ifndef O_BINARY
27 #ifdef _O_BINARY
28 #define O_BINARY _O_BINARY
29 #else
30 #define O_BINARY 0
31 #endif
32 #endif
33 
34 #include "filemap.h"
35 
36 int
37 filemap(const char *name,
38         void (*processor)(const void *, size_t, const char *, void *arg),
39         void *arg)
40 {
41   size_t nbytes;
42   int fd;
43   int n;
44   struct stat sb;
45   void *p;
46 
47   fd = open(name, O_RDONLY|O_BINARY);
48   if (fd < 0) {
49     perror(name);
50     return 0;
51   }
52   if (fstat(fd, &sb) < 0) {
53     perror(name);
54     close(fd);
55     return 0;
56   }
57   if (!S_ISREG(sb.st_mode)) {
58     fprintf(stderr, "%s: not a regular file\n", name);
59     close(fd);
60     return 0;
61   }
62   if (sb.st_size > XML_MAX_CHUNK_LEN) {
63     close(fd);
64     return 2;  /* Cannot be passed to XML_Parse in one go */
65   }
66 
67   nbytes = sb.st_size;
68   /* malloc will return NULL with nbytes == 0, handle files with size 0 */
69   if (nbytes == 0) {
70     static const char c = '\0';
71     processor(&c, 0, name, arg);
72     close(fd);
73     return 1;
74   }
75   p = malloc(nbytes);
76   if (!p) {
77     fprintf(stderr, "%s: out of memory\n", name);
78     close(fd);
79     return 0;
80   }
81   n = read(fd, p, nbytes);
82   if (n < 0) {
83     perror(name);
84     free(p);
85     close(fd);
86     return 0;
87   }
88   if (n != nbytes) {
89     fprintf(stderr, "%s: read unexpected number of bytes\n", name);
90     free(p);
91     close(fd);
92     return 0;
93   }
94   processor(p, nbytes, name, arg);
95   free(p);
96   close(fd);
97   return 1;
98 }
99