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
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 DIRECTORY_MODE S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH
52#define FILE_MODE S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH
53
54#define ASSERT_CTX(__ctx) \
55 if (__ctx == NULL) \
56 return CF_ERROR_FILE_INVALID_CTX
57
58#define ASSERT_ARGS(x) \
59 if ((x)) \
60 return CF_ERROR_FILE_INVALID_ARGS
61
62typedef struct __cf_file_ctx__
63{
64 int fd;
65 char path[1024];
66 CF_FILE_FLAG flag;
67} CF_FILE_CONTEXT;
68
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
84/**
85 * 파일 열기
86 *
87 * \return 성공 시, CF_OK; 실패 시, 오류 코드
88 *
89 * \param ctx 파일 컨텍스트
90 * \param path 파일 경로
91 * \param flag 파일 열기 플래그
92 *
93 * \see CF_FILE_FLAG
94 */
95int
96CF_File_Open (cf_ctx * ctx,
97 const char * path,
98 const CF_FILE_FLAG flag)
99{
100 int fd = 0;
101 int result = 0;
102 int osflag = 0;
103
104 CF_FILE_CONTEXT * context = NULL;
105
106 ASSERT_CTX (ctx);
107 ASSERT_ARGS (path == NULL);
108
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;
119
120 osflag = CF_File_Local_ConvertFlag (flag) | O_BINARY;
121
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;
129
130 *ctx = context;
131 }
132 CATCH_IF (result < 0)
133 {
134 CF_File_Close ((cf_ctx) context);
135 }
136
137 return result;
138}
139
140/**
141 * 파일 닫기
142 *
143 * \return 성공 시, CF_OK; 실패 시, 오류 코드
144 *
145 * \param ctx 파일 컨텍스트
146 */
147int
148CF_File_Close (cf_ctx ctx)
149{
150 int result = 0;
151 int fd = 0;
152
153 CF_FILE_CONTEXT * context = (CF_FILE_CONTEXT *) ctx;
154
155 ASSERT_CTX (context);
156 ASSERT_ARGS (context->fd < 0);
157
158 fd = context->fd;
159
160 free (context);
161
162 result = close (fd);
163 if (result < 0)
164 return CF_ERROR_FILE_CLOSE;
165
166 return CF_OK;
167}
168
169/**
170 * 파일 읽기
171 *
172 * \return 성공 시, 읽은 바이트 수; 실패 시, 오류 코드
173 *
174 * \param ctx 파일 컨텍스트
175 * \param buf 데이터를 저장할 메모리
176 * \param len 데이터를 저장할 메모리의 크기
177 */
178int
179CF_File_Read (const cf_ctx ctx,
180 void * buf,
181 const size_t len)
182{
183 int result = 0;
184
185 CF_FILE_CONTEXT * context = (CF_FILE_CONTEXT *) ctx;
186
187 ASSERT_CTX (context);
188 ASSERT_ARGS (context->fd < 0);
189 ASSERT_ARGS (buf == NULL);
190
191 result = (int) read (context->fd, buf, len);
192 if (result < 0)
193 return CF_ERROR_FILE_READ;
194
195 return result;
196}
197
198/**
199 * 파일 쓰기
200 *
201 * \return 성공 시, CF_OK; 실패 시, 오류 코드
202 *
203 * \param ctx 파일 컨텍스트
204 * \param buf 데이터가 저장된 메모리
205 * \param len 쓸 데이터의 길이
206 */
207int
208CF_File_Write (const cf_ctx ctx,
209 const void * buf,
210 const size_t len)
211{
212 int result = 0;
213
214 CF_FILE_CONTEXT * context = (CF_FILE_CONTEXT *) ctx;
215
216 ASSERT_CTX (context);
217 ASSERT_ARGS (context->fd < 0);
218 ASSERT_ARGS (buf == NULL);
219
220 result = (int) write (context->fd, buf, len);
221 if (result != len)
222 return CF_ERROR_FILE_WRITE;
223
224 return CF_OK;
225}
226
227/**
228 * 파일 크기 얻기
229 *
230 * \return 성공 시, 파일 크기; 실패 시, 오류 코드
231 *
232 * \param path 파일 경로
233 */
234int
235CF_File_GetSize (const char * path)
236{
237 int length = 0;
238 int fd = 0;
239
240 CF_FILE_CONTEXT * context = NULL;
241
242 ASSERT_ARGS (path == NULL);
243
244 fd = CF_File_Open ((cf_ctx *)&context, path, CF_FILE_READ);
245 if (fd < 0)
246 return CF_ERROR_FILE_OPEN;
247
248 length = (int) lseek (fd, 0, SEEK_END);
249 if (length < 0)
250 return CF_ERROR_FILE_GET_SIZE;
251
252 CF_File_Close ((cf_ctx)context);
253
254 return length;
255}
256
257/**
258 * 파일 및 디렉터리 존재 여부 검사
259 *
260 * \return 존재 시, CF_TRUE; 아니면, CF_FALSE
261 *
262 * \param path 파일 및 디렉터리 경로
263 */
264CF_BOOL
265CF_File_Exists (const char * path)
266{
267 return (access (path, F_OK) == 0) ? CF_TRUE : CF_FALSE;
268}
269
270/**
271 * 디렉터리 생성
272 *
273 * \return 성공 시, CF_OK; 실패 시, 오류 코드
274 *
275 * \param path 생성할 디렉터리 경로
276 */
277int
278CF_File_MakeDirectory (const char * path)
279{
280 int result = 0;
281 size_t length = 0;
282 char * fullpath = NULL;
283 char stepPath[256] = {0x00,};
284
285 char * f = NULL;
286 char * d = NULL;
287
288 ASSERT_ARGS (path == NULL);
289
290 length = strlen (path);
291 fullpath = (char *) calloc (length + 2, 1);
292 if (!fullpath)
293 return CF_ERROR_FILE_ALLOCATE_BUFFER;
294
295 f = fullpath;
296 d = stepPath;
297
298 snprintf (fullpath, length + 1, "%s%c", path, DELIMITER);
299
300 for (*d++ = *f++ ; *f ; *d++ = *f++)
301 {
302 if (*f != DELIMITER)
303 continue;
304
305 if (CF_File_Exists (stepPath))
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}
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.