Add IS_ALIGNED macro to test alignment of a pointer
[bertos.git] / bertos / fs / fat.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2009 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \brief FatFS: kfile interface for FatFS module by ChaN.
34  *
35  *
36  * \author Luca Ottaviano <lottaviano@develer.com>
37  *
38  */
39
40 #include "fat.h"
41
42 static size_t fatfile_read(struct KFile *_fd, void *buf, size_t size)
43 {
44         FatFile *fd = FATFILE_CAST(_fd);
45         UINT count;
46         fd->error_code = f_read(&fd->fat_file, buf, size, &count);
47         return count;
48 }
49
50 static size_t fatfile_write(struct KFile *_fd, const void *buf, size_t size)
51 {
52         FatFile *fd = FATFILE_CAST(_fd);
53         UINT count;
54         fd->error_code = f_write(&fd->fat_file, buf, size, &count);
55         return count;
56 }
57
58 static int fatfile_close(struct KFile *_fd)
59 {
60         FatFile *fd = FATFILE_CAST(_fd);
61         fd->error_code = f_close(&fd->fat_file);
62         if (fd->error_code)
63                 return EOF;
64         else
65                 return 0;
66 }
67
68 static kfile_off_t fatfile_seek(struct KFile *_fd, kfile_off_t offset, KSeekMode whence)
69 {
70         /* clip at start-of-file
71          * don't clip at end-of-file when in write mode
72          */
73         FatFile *fd = FATFILE_CAST(_fd);
74         DWORD lseek_offset = 0;
75         switch (whence)
76         {
77         case KSM_SEEK_SET:
78                 if (offset > 0)
79                         lseek_offset = (DWORD) offset;
80                 break;
81         case KSM_SEEK_CUR:
82                 if (offset > 0)
83                         lseek_offset = fd->fat_file.fptr + (DWORD) offset;
84                 else
85                 {
86                         if (fd->fat_file.fptr > (DWORD) (-offset))
87                                 lseek_offset = fd->fat_file.fptr - (DWORD)(-offset);
88                 }
89                 break;
90         case KSM_SEEK_END:
91                 if (offset > 0)
92                         lseek_offset = fd->fat_file.fsize + (DWORD) offset;
93                 else
94                 {
95                         if (fd->fat_file.fsize > (DWORD) (-offset))
96                                 lseek_offset = fd->fat_file.fsize + (DWORD) offset;
97                 }
98                 break;
99         }
100         fd->error_code = f_lseek(&fd->fat_file, lseek_offset);
101         if ((fd->error_code) || (fd->fat_file.fptr != lseek_offset))
102                 return EOF;
103         else
104                 /* TODO: this conversion may overflow */
105                 return (kfile_off_t)fd->fat_file.fptr;
106 }
107
108 static int fatfile_flush(struct KFile *_fd)
109 {
110         FatFile *fd = FATFILE_CAST(_fd);
111         fd->error_code = f_sync(&fd->fat_file);
112         if (fd->error_code)
113                 return EOF;
114         else
115                 return 0;
116 }
117
118 static int fatfile_error(struct KFile *_fd)
119 {
120         FatFile *fd = FATFILE_CAST(_fd);
121         return (int)fd->error_code;
122 }
123
124 static void fatfile_clearerr(struct KFile *_fd)
125 {
126         FatFile *fd = FATFILE_CAST(_fd);
127         fd->error_code = FR_OK;
128 }
129
130 FRESULT fatfile_open(FatFile *file, const char *file_path, BYTE mode)
131 {
132         DB(file->fd._type = KFT_FATFILE);
133         file->fd.read = fatfile_read;
134         file->fd.write = fatfile_write;
135         file->fd.reopen = 0;
136         file->fd.close = fatfile_close;
137         file->fd.seek = fatfile_seek;
138         file->fd.flush = fatfile_flush;
139         file->fd.error = fatfile_error;
140         file->fd.clearerr = fatfile_clearerr;
141         return f_open(&file->fat_file, file_path, mode);
142 }
143