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

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

#1 fix file-context bug

File size: 6.4 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 length = 0;
237 int result = 0;
238
239 CF_FILE_CONTEXT * context = NULL;
240
241 ASSERT_ARGS (path == NULL);
242
243 result = CF_File_Open ((cf_ctx *)&context, path, CF_FILE_READ);
244 if (result < 0)
245 return CF_ERROR_FILE_OPEN;
246
247 length = (int) lseek (context->fd, 0, SEEK_END);
248 if (length < 0)
249 return CF_ERROR_FILE_GET_SIZE;
250
251 CF_File_Close ((cf_ctx)context);
252
253 return length;
254}
255
256/**
257 * 파일 및 디렉터리 존재 여부 검사
258 *
259 * \return 존재 시, CF_TRUE; 아니면, CF_FALSE
260 *
261 * \param path 파일 및 디렉터리 경로
262 */
263CF_BOOL
264CF_File_Exists (const char * path)
265{
266 return (access (path, F_OK) == 0) ? CF_TRUE : CF_FALSE;
267}
268
269/**
270 * 디렉터리 생성
271 *
272 * \return 성공 시, CF_OK; 실패 시, 오류 코드
273 *
274 * \param path 생성할 디렉터리 경로
275 */
276int
277CF_File_MakeDirectory (const char * path)
278{
279 int result = 0;
280 size_t length = 0;
281 char * fullpath = NULL;
282 char stepPath[256] = {0x00,};
283
284 char * f = NULL;
285 char * d = NULL;
286
287 ASSERT_ARGS (path == NULL);
288
289 length = strlen (path);
290 fullpath = (char *) calloc (length + 2, 1);
291 if (!fullpath)
292 return CF_ERROR_FILE_ALLOCATE_BUFFER;
293
294 f = fullpath;
295 d = stepPath;
296
297 snprintf (fullpath, length + 1, "%s%c", path, DELIMITER);
298
299 for (*d++ = *f++ ; *f ; *d++ = *f++)
300 {
301 if (*f != DELIMITER)
302 continue;
303
304 if (CF_File_Exists (stepPath))
305 continue;
306
307#define DIRECTORY_MODE (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
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.