source: libcf/trunk/src/cf_file.c@ 157

Last change on this file since 157 was 157, checked in by cheese, 10 years ago

#1 fix memory leakage

File size: 6.6 KB
Line 
1/**
2 * \file cf_file.c
3 *
4 * \author myusgun <myusgun@gmail.com>
5 *
6 * \brief 파일 입출력 구현
7 */
8#include "cf_file.h"
9#include "cf_local.h"
10#include "cf_error.h"
11
12#include <stdio.h>
13#include <string.h>
14#include <fcntl.h>
15#include <errno.h>
16#include <sys/stat.h>
17
18#if defined(_WIN32) || defined(_WIN64)
19# include <io.h>
20# include <direct.h>
21
22# define DELIMITER '\\'
23# define mkdir(a,b) _mkdir (a)
24# define access(a,b) _access (a,b)
25
26# define F_OK 0
27# define W_OK 2
28# define R_OK 4
29
30/*------------------------------*/
31# define S_IWUSR _S_IWRITE
32# define S_IRUSR _S_IREAD
33# define S_IXUSR _S_IEXEC
34/*------------------------------*/
35# define S_IRGRP 0x00000000
36# define S_IWGRP 0x00000000
37# define S_IXGRP 0x00000000
38/*------------------------------*/
39# define S_IROTH 0x00000000
40# define S_IWOTH 0x00000000
41# define S_IXOTH 0x00000000
42/*------------------------------*/
43# define S_IRWXU 0x00000000
44#else // #if defined(_WIN32) || defined(_WIN64)
45# include <unistd.h>
46
47# define DELIMITER '/'
48# define O_BINARY 0x00000000
49#endif // #if defined(_WIN32) || defined(_WIN64)
50
51#define ASSERT_CTX(__ctx) \
52 if (__ctx == NULL) \
53 return CF_ERROR_FILE_INVALID_CTX
54
55#define ASSERT_ARGS(x) \
56 if ((x)) \
57 return CF_ERROR_FILE_INVALID_ARGS
58
59typedef struct __cf_file_ctx__
60{
61 int fd;
62 char path[1024];
63 CF_FILE_FLAG flag;
64} CF_FILE_CONTEXT;
65
66static int
67CF_File_Local_ConvertFlag (const CF_FILE_FLAG flag)
68{
69 int result = 0;
70
71 if (flag & CF_FILE_READ) result |= O_RDONLY;
72 if (flag & CF_FILE_WRITE) result |= O_WRONLY;
73 if (flag & CF_FILE_RW) result |= O_RDWR;
74 if (flag & CF_FILE_CREATE) result |= O_CREAT;
75 if (flag & CF_FILE_TRUNC) result |= O_TRUNC;
76 if (flag & CF_FILE_APPEND) result |= O_APPEND;
77
78 return result;
79}
80
81/**
82 * 파일 열기
83 *
84 * \return 성공 시, CF_OK; 실패 시, 오류 코드
85 *
86 * \param ctx 파일 컨텍스트
87 * \param path 파일 경로
88 * \param flag 파일 열기 플래그
89 *
90 * \see CF_FILE_FLAG
91 */
92int
93CF_File_Open (cf_ctx * ctx,
94 const char * path,
95 const CF_FILE_FLAG flag)
96{
97 int fd = 0;
98 int result = 0;
99 int osflag = 0;
100
101 CF_FILE_CONTEXT * context = NULL;
102
103 ASSERT_CTX (ctx);
104 ASSERT_ARGS (path == NULL);
105
106 TRY
107 {
108 context = NEWCTX (CF_FILE_CONTEXT);
109 if (context == NULL)
110 {
111 result = CF_ERROR_FILE_CREATE_CTX;
112 TRY_BREAK;
113 }
114 context->flag = flag;
115 context->fd = -1;
116
117 osflag = CF_File_Local_ConvertFlag (flag) | O_BINARY;
118
119#define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
120 fd = open (path, osflag, FILE_MODE);
121 if (fd < 0)
122 {
123 result = CF_ERROR_FILE_OPEN;
124 TRY_BREAK;
125 }
126 context->fd = fd;
127 snprintf (context->path, sizeof (context->path) - 1, "%s", path);
128
129 *ctx = context;
130 }
131 CATCH_IF (result < 0)
132 {
133 CF_File_Close ((cf_ctx) context);
134 }
135
136 return result;
137}
138
139/**
140 * 파일 닫기
141 *
142 * \return 성공 시, CF_OK; 실패 시, 오류 코드
143 *
144 * \param ctx 파일 컨텍스트
145 */
146int
147CF_File_Close (cf_ctx ctx)
148{
149 int result = 0;
150 int fd = 0;
151
152 CF_FILE_CONTEXT * context = (CF_FILE_CONTEXT *) ctx;
153
154 ASSERT_CTX (context);
155 ASSERT_ARGS (context->fd < 0);
156
157 fd = context->fd;
158
159 free (context);
160
161 result = close (fd);
162 if (result < 0)
163 return CF_ERROR_FILE_CLOSE;
164
165 return CF_OK;
166}
167
168/**
169 * 파일 읽기
170 *
171 * \return 성공 시, 읽은 바이트 수; 실패 시, 오류 코드
172 *
173 * \param ctx 파일 컨텍스트
174 * \param buf 데이터를 저장할 메모리
175 * \param len 데이터를 저장할 메모리의 크기
176 */
177int
178CF_File_Read (const cf_ctx ctx,
179 void * buf,
180 const size_t len)
181{
182 int result = 0;
183
184 CF_FILE_CONTEXT * context = (CF_FILE_CONTEXT *) ctx;
185
186 ASSERT_CTX (context);
187 ASSERT_ARGS (context->fd < 0);
188 ASSERT_ARGS (buf == NULL);
189
190 result = (int) read (context->fd, buf, len);
191 if (result < 0)
192 return CF_ERROR_FILE_READ;
193
194 return result;
195}
196
197/**
198 * 파일 쓰기
199 *
200 * \return 성공 시, CF_OK; 실패 시, 오류 코드
201 *
202 * \param ctx 파일 컨텍스트
203 * \param buf 데이터가 저장된 메모리
204 * \param len 쓸 데이터의 길이
205 */
206int
207CF_File_Write (const cf_ctx ctx,
208 const void * buf,
209 const size_t len)
210{
211 int result = 0;
212
213 CF_FILE_CONTEXT * context = (CF_FILE_CONTEXT *) ctx;
214
215 ASSERT_CTX (context);
216 ASSERT_ARGS (context->fd < 0);
217 ASSERT_ARGS (buf == NULL);
218
219 result = (int) write (context->fd, buf, len);
220 if (result != len)
221 return CF_ERROR_FILE_WRITE;
222
223 return CF_OK;
224}
225
226/**
227 * 파일 크기 얻기
228 *
229 * \return 성공 시, 파일 크기; 실패 시, 오류 코드
230 *
231 * \param path 파일 경로
232 */
233int
234CF_File_GetSize (const char * path)
235{
236 int result = 0;
237
238 CF_FILE_CONTEXT * context = NULL;
239
240 ASSERT_ARGS (path == NULL);
241
242 TRY
243 {
244 result = CF_File_Open ((cf_ctx *)&context, path, CF_FILE_READ);
245 if (result < 0)
246 {
247 result = CF_ERROR_FILE_OPEN;
248 TRY_BREAK;
249 }
250
251 result = (int) lseek (context->fd, 0, SEEK_END);
252 if (result < 0)
253 {
254 result = CF_ERROR_FILE_GET_SIZE;
255 TRY_BREAK;
256 }
257 }
258 NO_CATCH;
259
260 CF_File_Close ((cf_ctx)context);
261
262 return result;
263}
264
265/**
266 * 파일 및 디렉터리 존재 여부 검사
267 *
268 * \return 존재 시, CF_TRUE; 아니면, CF_FALSE
269 *
270 * \param path 파일 및 디렉터리 경로
271 */
272CF_BOOL
273CF_File_Exists (const char * path)
274{
275 return (access (path, F_OK) == 0) ? CF_TRUE : CF_FALSE;
276}
277
278/**
279 * 디렉터리 생성
280 *
281 * \return 성공 시, CF_OK; 실패 시, 오류 코드
282 *
283 * \param path 생성할 디렉터리 경로
284 */
285int
286CF_File_MakeDirectory (const char * path)
287{
288 int result = 0;
289 size_t length = 0;
290 char * fullpath = NULL;
291 char stepPath[256] = {0x00,};
292
293 char * f = NULL;
294 char * d = NULL;
295
296 ASSERT_ARGS (path == NULL);
297
298 TRY
299 {
300 length = strlen (path);
301 fullpath = (char *) calloc (length + 2, 1);
302 if (!fullpath)
303 {
304 result = CF_ERROR_FILE_ALLOCATE_BUFFER;
305 TRY_BREAK;
306 }
307
308 f = fullpath;
309 d = stepPath;
310
311 snprintf (fullpath, length + 1, "%s%c", path, DELIMITER);
312
313 for (*d++ = *f++ ; *f ; *d++ = *f++)
314 {
315 if (*f != DELIMITER)
316 continue;
317
318 if (CF_File_Exists (stepPath))
319 continue;
320
321#define DIRECTORY_MODE (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
322 result = mkdir (stepPath, DIRECTORY_MODE);
323 if (result && errno != EEXIST)
324 {
325 result = CF_ERROR_FILE_MAKE_DIRECTORY;
326 break;
327 }
328 }
329 }
330 NO_CATCH;
331
332 if (fullpath) free (fullpath);
333
334 return result;
335}
336
337/**
338 * 컨텍스트가 열고 있는 파일의 경로를 가져옴
339 *
340 * \return 성공 시, CF_OK; 실패 시, 오류 코드
341 *
342 * \param ctx 파일 컨텍스트
343 * \param path 파일 경로를 저장할 충분한 공간의 메모리
344 */
345int
346CF_File_GetPath (const cf_ctx ctx,
347 char * path)
348{
349 CF_FILE_CONTEXT * context = (CF_FILE_CONTEXT *) ctx;
350
351 ASSERT_CTX (context);
352 ASSERT_ARGS (path == NULL);
353
354 snprintf (path, sizeof (context->path), "%s", context->path);
355
356 return CF_OK;
357}
Note: See TracBrowser for help on using the repository browser.