1 /*
2 * ME3D 3-D Modeler Program
3 * Copyright (C) 1998 Sam Revitch
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 /* file utility functions */
21
22 /* (this program was written with basic portability in mind) */
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <sys/mman.h>
32 #include <stdarg.h>
33
34 #include "file_utils.h"
35
36 #ifdef MEMWATCH
37 #include "memwatch.h"
38 #endif
39
40
41 gint fu_pointers_equal(gconstpointer p1, gconstpointer p2);
42
fu_pointers_equal(gconstpointer p1,gconstpointer p2)43 gint fu_pointers_equal(gconstpointer p1, gconstpointer p2)
44 { if(p1 == p2) return TRUE; return FALSE; }
45
46
fu_open(const gchar * name,gint create)47 struct fu_file *fu_open(const gchar *name, gint create)
48 {
49 struct fu_file *file;
50 int fd;
51
52 g_return_val_if_fail(name != NULL, NULL);
53
54 if(create)
55 fd = open(name, O_RDWR | O_CREAT, 0644);
56 else
57 fd = open(name, O_RDONLY);
58
59 if(fd == -1)
60 return NULL;
61
62 file = (struct fu_file*) malloc(sizeof(struct fu_file));
63 file->fd = fd;
64
65
66 if(create)
67 file->fp = fdopen( fd, "a+" );
68 else
69 file->fp = fdopen( fd, "r" );
70
71 if( file->fp == NULL ) {
72 printf( "%s: fdopen failed. errno is %i\n", __FUNCTION__, errno );
73 if( errno == EINVAL )
74 printf( "\terrno is EINVAL - invalid 'mode' arg\n" );
75 }
76
77
78 file->len_ht = g_hash_table_new(g_direct_hash, fu_pointers_equal);
79 return file;
80 }
81
fu_close(struct fu_file * file)82 void fu_close(struct fu_file *file)
83 {
84 g_return_if_fail(file != NULL);
85
86 fflush( file->fp );
87 close(file->fd);
88
89 g_hash_table_destroy(file->len_ht);
90 free(file);
91 }
92
fu_file_size(struct fu_file * file)93 guint fu_file_size(struct fu_file *file)
94 {
95 struct stat fu_stat;
96
97 g_return_val_if_fail(file != NULL, 0);
98 fstat(file->fd, &fu_stat);
99 return fu_stat.st_size;
100 }
101
fu_map_block(struct fu_file * file,guint start,guint len)102 guchar *fu_map_block(struct fu_file *file, guint start, guint len)
103 {
104 guchar *r;
105
106 g_return_val_if_fail(file != NULL, NULL);
107 r = (guchar*) mmap(NULL, (size_t)len, PROT_READ,
108 MAP_PRIVATE, file->fd, (off_t)start);
109 g_return_val_if_fail(r != (guchar*) -1, NULL);
110
111 g_hash_table_insert(file->len_ht, r, (gpointer)len);
112 return r;
113 }
114
fu_unmap_block(struct fu_file * file,guchar * block)115 void fu_unmap_block(struct fu_file *file, guchar *block)
116 {
117 gpointer tmp;
118 guint len;
119
120 g_return_if_fail(file != NULL);
121
122 /* just doing some casting, to silence compiler warnings */
123 tmp = g_hash_table_lookup(file->len_ht, block);
124 len = (guint)tmp;
125 g_return_if_fail(len != 0);
126
127 g_hash_table_remove(file->len_ht, block);
128 munmap(block, len);
129 }
130
fu_write_block(struct fu_file * file,guchar * block,guint len)131 void fu_write_block(struct fu_file *file, guchar *block, guint len)
132 {
133 g_return_if_fail(file != NULL);
134
135 write(file->fd, block, (size_t)len);
136 }
137
fu_truncate(struct fu_file * file,guint size)138 void fu_truncate(struct fu_file *file, guint size)
139 {
140 g_return_if_fail(file != NULL);
141
142 ftruncate(file->fd, size);
143 }
144
fu_seek(struct fu_file * file,gint pos)145 void fu_seek(struct fu_file *file, gint pos)
146 {
147 g_return_if_fail(file != NULL);
148
149 lseek(file->fd, (off_t) pos, SEEK_SET);
150 }
151
fu_gets(struct fu_file * file,gchar * buf,guint len)152 gint fu_gets(struct fu_file *file, gchar *buf, guint len)
153 {
154 guint pos = 0;
155 off_t offset;
156
157 g_return_val_if_fail(file != NULL, 0);
158 g_return_val_if_fail(buf != NULL, 0);
159 g_return_val_if_fail(len > 0, 0);
160
161 offset = lseek(file->fd, 0, SEEK_CUR);
162
163 /* this is a cool yet inefficient one */
164 pos = read(file->fd, buf, len);
165 if(pos <= 0)
166 return -1;
167
168 if(pos < len)
169 len = pos;
170
171 pos = 0;
172 while(pos < len)
173 {
174 if(buf[pos] == '\n') {
175 buf[pos] = '\0';
176 lseek(file->fd, (off_t) (offset + pos + 1), SEEK_SET);
177 return pos;
178 }
179 pos++;
180 }
181
182 buf[len - 1] = '\0';
183 return (len - 1);
184 }
185
fu_puts(struct fu_file * file,gchar * src)186 gint fu_puts(struct fu_file *file, gchar *src)
187 {
188 gint len;
189
190 g_return_val_if_fail(file != NULL, 0);
191
192 len = strlen(src);
193 return (gint) write(file->fd, src, len);
194 }
195
fu_printf(struct fu_file * file,gchar * fmt,...)196 gint fu_printf(struct fu_file *file, gchar *fmt, ...)
197 {
198 va_list ap;
199 gchar buf[1024]; /* bigger is better */
200 gint length;
201
202 g_return_val_if_fail(file != NULL, 0);
203
204 va_start(ap, fmt);
205 length = vsnprintf(buf, 1024, fmt, ap);
206
207 return (gint) write(file->fd, buf, length);
208 }
209