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
RevLine 
[4]1/**
[128]2 * \file cf_file.c
[117]3 *
[128]4 * \author myusgun <myusgun@gmail.com>
5 *
[119]6 * \brief 파일 입출력 구현
[4]7 */
8#include "cf_file.h"
[66]9#include "cf_local.h"
[40]10#include "cf_error.h"
[4]11
[41]12#include <stdio.h>
[151]13#include <string.h>
[90]14#include <fcntl.h>
[41]15#include <errno.h>
16#include <sys/stat.h>
17
[50]18#if defined(_WIN32) || defined(_WIN64)
[4]19# include <io.h>
[55]20# include <direct.h>
[14]21
[41]22# define DELIMITER '\\'
23# define mkdir(a,b) _mkdir (a)
24# define access(a,b) _access (a,b)
25
[43]26# define F_OK 0
27# define W_OK 2
28# define R_OK 4
29
[41]30/*------------------------------*/
[14]31# define S_IWUSR _S_IWRITE
32# define S_IRUSR _S_IREAD
33# define S_IXUSR _S_IEXEC
[41]34/*------------------------------*/
[14]35# define S_IRGRP 0x00000000
36# define S_IWGRP 0x00000000
37# define S_IXGRP 0x00000000
[41]38/*------------------------------*/
[14]39# define S_IROTH 0x00000000
40# define S_IWOTH 0x00000000
41# define S_IXOTH 0x00000000
[41]42/*------------------------------*/
43# define S_IRWXU 0x00000000
[50]44#else // #if defined(_WIN32) || defined(_WIN64)
[4]45# include <unistd.h>
[41]46
47# define DELIMITER '/'
[26]48# define O_BINARY 0x00000000
[50]49#endif // #if defined(_WIN32) || defined(_WIN64)
[4]50
[151]51#define ASSERT_CTX(__ctx) \
52 if (__ctx == NULL) \
53 return CF_ERROR_FILE_INVALID_CTX
54
[85]55#define ASSERT_ARGS(x) \
56 if ((x)) \
[55]57 return CF_ERROR_FILE_INVALID_ARGS
58
[151]59typedef struct __cf_file_ctx__
60{
61 int fd;
62 char path[1024];
63 CF_FILE_FLAG flag;
64} CF_FILE_CONTEXT;
65
[90]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
[35]81/**
82 * 파일 열기
83 *
[151]84 * \return 성공 시, CF_OK; 실패 시, 오류 코드
[35]85 *
[151]86 * \param ctx 파일 컨텍스트
[119]87 * \param path 파일 경로
88 * \param flag 파일 열기 플래그
[35]89 *
[119]90 * \see CF_FILE_FLAG
[35]91 */
[4]92int
[151]93CF_File_Open (cf_ctx * ctx,
94 const char * path,
[16]95 const CF_FILE_FLAG flag)
[4]96{
[151]97 int fd = 0;
[55]98 int result = 0;
[93]99 int osflag = 0;
[4]100
[151]101 CF_FILE_CONTEXT * context = NULL;
102
103 ASSERT_CTX (ctx);
[55]104 ASSERT_ARGS (path == NULL);
105
[151]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;
[93]116
[151]117 osflag = CF_File_Local_ConvertFlag (flag) | O_BINARY;
[4]118
[154]119#define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
[151]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;
[154]127 snprintf (context->path, sizeof (context->path) - 1, "%s", path);
[4]128
[151]129 *ctx = context;
130 }
131 CATCH_IF (result < 0)
132 {
133 CF_File_Close ((cf_ctx) context);
134 }
[4]135
136 return result;
137}
138
[35]139/**
140 * 파일 닫기
141 *
[119]142 * \return 성공 시, CF_OK; 실패 시, 오류 코드
[35]143 *
[151]144 * \param ctx 파일 컨텍스트
[35]145 */
[4]146int
[151]147CF_File_Close (cf_ctx ctx)
[4]148{
149 int result = 0;
[151]150 int fd = 0;
[4]151
[151]152 CF_FILE_CONTEXT * context = (CF_FILE_CONTEXT *) ctx;
[4]153
[151]154 ASSERT_CTX (context);
155 ASSERT_ARGS (context->fd < 0);
156
157 fd = context->fd;
158
159 free (context);
160
[4]161 result = close (fd);
162 if (result < 0)
163 return CF_ERROR_FILE_CLOSE;
164
165 return CF_OK;
166}
167
[35]168/**
169 * 파일 읽기
170 *
[119]171 * \return 성공 시, 읽은 바이트 수; 실패 시, 오류 코드
[35]172 *
[151]173 * \param ctx 파일 컨텍스트
[119]174 * \param buf 데이터를 저장할 메모리
175 * \param len 데이터를 저장할 메모리의 크기
[35]176 */
[4]177int
[151]178CF_File_Read (const cf_ctx ctx,
[4]179 void * buf,
180 const size_t len)
181{
[55]182 int result = 0;
[151]183
184 CF_FILE_CONTEXT * context = (CF_FILE_CONTEXT *) ctx;
185
186 ASSERT_CTX (context);
187 ASSERT_ARGS (context->fd < 0);
[55]188 ASSERT_ARGS (buf == NULL);
[4]189
[151]190 result = (int) read (context->fd, buf, len);
[4]191 if (result < 0)
192 return CF_ERROR_FILE_READ;
193
[26]194 return result;
[4]195}
196
[35]197/**
198 * 파일 쓰기
199 *
[119]200 * \return 성공 시, CF_OK; 실패 시, 오류 코드
[35]201 *
[151]202 * \param ctx 파일 컨텍스트
[119]203 * \param buf 데이터가 저장된 메모리
204 * \param len 쓸 데이터의 길이
[35]205 */
[4]206int
[151]207CF_File_Write (const cf_ctx ctx,
[4]208 const void * buf,
209 const size_t len)
210{
[55]211 int result = 0;
[151]212
213 CF_FILE_CONTEXT * context = (CF_FILE_CONTEXT *) ctx;
214
215 ASSERT_CTX (context);
216 ASSERT_ARGS (context->fd < 0);
[55]217 ASSERT_ARGS (buf == NULL);
[4]218
[151]219 result = (int) write (context->fd, buf, len);
[4]220 if (result != len)
221 return CF_ERROR_FILE_WRITE;
222
223 return CF_OK;
224}
225
[35]226/**
227 * 파일 크기 얻기
228 *
[119]229 * \return 성공 시, 파일 크기; 실패 시, 오류 코드
[35]230 *
[119]231 * \param path 파일 경로
[35]232 */
[4]233int
[94]234CF_File_GetSize (const char * path)
[4]235{
[154]236 int result = 0;
[4]237
[151]238 CF_FILE_CONTEXT * context = NULL;
239
[94]240 ASSERT_ARGS (path == NULL);
[55]241
[157]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 }
[94]250
[157]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;
[4]259
[151]260 CF_File_Close ((cf_ctx)context);
[94]261
[157]262 return result;
[4]263}
[41]264
265/**
[109]266 * 파일 및 디렉터리 존재 여부 검사
267 *
[119]268 * \return 존재 시, CF_TRUE; 아니면, CF_FALSE
[109]269 *
[119]270 * \param path 파일 및 디렉터리 경로
[109]271 */
272CF_BOOL
273CF_File_Exists (const char * path)
274{
275 return (access (path, F_OK) == 0) ? CF_TRUE : CF_FALSE;
276}
277
278/**
[41]279 * 디렉터리 생성
280 *
[119]281 * \return 성공 시, CF_OK; 실패 시, 오류 코드
[41]282 *
[119]283 * \param path 생성할 디렉터리 경로
[41]284 */
285int
286CF_File_MakeDirectory (const char * path)
287{
288 int result = 0;
[151]289 size_t length = 0;
290 char * fullpath = NULL;
[41]291 char stepPath[256] = {0x00,};
292
[151]293 char * f = NULL;
294 char * d = NULL;
[41]295
[55]296 ASSERT_ARGS (path == NULL);
297
[157]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 }
[41]307
[157]308 f = fullpath;
309 d = stepPath;
[151]310
[157]311 snprintf (fullpath, length + 1, "%s%c", path, DELIMITER);
[151]312
[157]313 for (*d++ = *f++ ; *f ; *d++ = *f++)
314 {
315 if (*f != DELIMITER)
316 continue;
[41]317
[157]318 if (CF_File_Exists (stepPath))
319 continue;
[41]320
[154]321#define DIRECTORY_MODE (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
[157]322 result = mkdir (stepPath, DIRECTORY_MODE);
323 if (result && errno != EEXIST)
324 {
325 result = CF_ERROR_FILE_MAKE_DIRECTORY;
326 break;
327 }
328 }
[41]329 }
[157]330 NO_CATCH;
[41]331
[157]332 if (fullpath) free (fullpath);
333
334 return result;
[41]335}
[151]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.