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

Last change on this file since 151 was 151, checked in by cheese, 11 years ago

#1 fix interface and add util module

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