GadgetSeed  0.9.6
file.c
[詳解]
1 /** @file
2  @brief ファイル関数
3 
4  GadgetSeed のファイルシステムは FatFs を使用しています。
5 
6  参考 : http://elm-chan.org/fsw/ff/00index_e.html
7 
8  @date 2018.09.15
9  @date 2008.03.20
10  @author Takashi SHUDO
11 
12  @page file_system ファイルシステム
13 
14  GadgetSeedのファイルシステムは [FatFs](http://elm-chan.org/fsw/ff/00index_e.html) を使用しています。
15 
16  ファイルシステムを使用するには、以下のコンフィグ項目を有効にして下さい。
17 
18  * COMP_ENABLE_FATFS
19 
20  ---
21  @section file_api ファイルAPI
22 
23  include ファイル : file.h
24 
25  | API名 | 機能 |
26  |:--------------------------|:------------------------------|
27  | open_file() | @copybrief open_file |
28  | read_file() | @copybrief read_file |
29  | write_file() | @copybrief write_file |
30  | seek_file() | @copybrief seek_file |
31  | tell_file() | @copybrief tell_file |
32  | close_file() | @copybrief close_file |
33  | opendir_file() | @copybrief opendir_file |
34  | readdir_file() | @copybrief readdir_file |
35  | closedir_file() | @copybrief closedir_file |
36  | stat_file() | @copybrief stat_file |
37  | getfree_file() | @copybrief getfree_file |
38  | sync_file() | @copybrief sync_file |
39  | unlink_file() | @copybrief unlink_file |
40  | mkdir_file() | @copybrief mkdir_file |
41  | chmod_file() | @copybrief chmod_file |
42  | rename_file() | @copybrief rename_file |
43  | mkfs_file() | @copybrief mkfs_file |
44 
45 
46  ---
47  @section file_util_api ファイルユーティリティAPI
48 
49  include ファイル : file.h
50 
51  | API名 | 機能 |
52  |:--------------------------|:--------------------------------------|
53  | get_last_filename() | @copybrief get_last_filename |
54  | get_filename_extension() | @copybrief get_filename_extension |
55 */
56 
57 #include "file.h"
58 #include "device.h"
59 #include "storage.h"
60 #include "str.h"
61 #include "tkprintf.h"
62 #include "fs.h"
63 
64 //#define DEBUGTBITS 0x03
65 #include "dtprintf.h"
66 
67 // ファイルディスクリプタはスタティックに確保
68 #ifndef GSC_FS_MAX_FILE_NUM
69 #define GSC_FS_MAX_FILE_NUM 2 ///< $gsc オープンできる最大ファイル数
70 #endif
71 
72 extern struct st_filesystem *filesystems[];
73 extern struct st_storage_info storage[GSC_FS_VOLUME_NUM]; ///< ストレージデバイステーブル
74 
75 static struct st_file_desc {
76  int flg_used; ///< ファイルディスクリプタ使用フラグ
77  struct st_filesystem *fs; ///< ファイルシステム
78  void *fs_desc; ///< ファイルシステム用ディスクリプタ
79 } file_desc[GSC_FS_MAX_FILE_NUM];
80 
81 /**
82  @brief 全てのファイルディスクリプタを初期化する
83 */
84 void init_file(void)
85 {
86  int i;
87 
88  for(i=0; i<GSC_FS_MAX_FILE_NUM; i++) {
89  file_desc[i].flg_used = 0;
90  }
91 }
92 
93 /**
94  @brief ファイル名からストレージ番号を調べる
95 
96  @param path ファイル名
97 
98  @return ストレージ番号
99 */
100 int get_diskno(const uchar *path)
101 {
102  int devno = 0;
103 
104  if(path[1] == ':') {
105  if(('0' <= path[0]) && (path[0] <= '9')) {
106  devno = path[0] - '0';
107  }
108  }
109 
110  return devno;
111 }
112 
113 /**
114  @brief ファイル名からファイルシステムを調べる
115 
116  @param path ファイル名
117 
118  @return ファイルシステム
119 */
120 struct st_filesystem * get_filesystem(const uchar *path)
121 {
122  int devno;
123  struct st_filesystem *fs = 0;
124 
125  devno = get_diskno(path);
126 
127  if(devno >= GSC_FS_VOLUME_NUM) {
128  fs = 0; // デバイス無し
129  } else {
130  fs = filesystems[devno];
131  }
132 
133  return fs;
134 }
135 
136 /**
137  @brief ファイルを開く
138 
139  @param path ファイル名
140  @param flags 属性フラグ
141 
142  @return ファイルディスクリプタ(0:エラー)
143 */
144 int open_file(const uchar *path, int flags)
145 {
146  int i;
147  struct st_filesystem *fs;
148  void *fdesc;
149 
150  DTFPRINTF(0x01, "path = %s, flgas = %08X\n", path, flags);
151 
152  fs = get_filesystem(path);
153  if(fs == 0) {
154  return -1;
155  }
156 
157  for(i=0; i<GSC_FS_MAX_FILE_NUM; i++) {
158  if(file_desc[i].flg_used == 0) {
159  file_desc[i].fs = fs;
160  fdesc = fs->open(path, flags);
161  if(fdesc != 0) {
162  file_desc[i].fs_desc = fdesc;
163  file_desc[i].flg_used = 1;
164  return i;
165  } else {
166  //SYSERR_PRINT("cannot open file \"%s\" (%d)", path, res);
167  return -1;
168  }
169  }
170  }
171 
172  SYSERR_PRINT("cannot open file \"%s\" (GSC_FS_MAX_FILE_NUM)\n", path);
173 
174  return -1;
175 }
176 
177 #define ACCESS_SIZE 0x4000
178 
179 /**
180  @brief ファイルからデータを読み出す
181 
182  @param[in] int ファイルディスクリプタ
183  @param[out] buf 読み出しデータポインタ
184  @param[in] count 読み出しバイト数
185 
186  @return 読み出しバイト数(<0:エラー)
187 */
188 t_ssize read_file(int fd, void *buf, t_size count)
189 {
190  struct st_filesystem *fs;
191  int rtn = 0;
192 
193  DTFPRINTF(0x02, "fd = %d, buf = %p, count = %d\n", fd, buf, count);
194 
195  fs = file_desc[fd].fs;
196  if(fs == 0) {
197  return -1;
198  }
199 
200  if(fs->read != 0) {
201  rtn = fs->read(file_desc[fd].fs_desc, buf, count);
202  }
203 
204  return rtn;
205 }
206 
207 /**
208  @brief ファイルにデータを書き込む
209 
210  @param[in] fd ファイルディスクリプタ
211  @param[in] buf 書き込みデータポインタ
212  @param[in] count 書き込みバイト数
213 
214  @return 書き込みバイト数(<0:エラー)
215 */
216 t_ssize write_file(int fd, const void *buf, t_size count)
217 {
218  struct st_filesystem *fs;
219  int rtn = 0;
220 
221  DTFPRINTF(0x02, "fd = %d, buf = %p, count = %d\n", fd, buf, count);
222 
223  fs = file_desc[fd].fs;
224  if(fs == 0) {
225  return -1;
226  }
227 
228  if(fs->write != 0) {
229  rtn = fs->write(file_desc[fd].fs_desc, buf, count);
230  }
231 
232  return rtn;
233 }
234 
235 /**
236  @brief ファイルアクセス位置の設定
237 
238  @param[in] fd ファイルディスクリプタ
239  @param[in] offset 移動バイト数
240  @param[in] whence 移動基準位置
241 
242  @return 先頭からのオフセット位置バイト数
243 */
244 t_ssize seek_file(int fd, t_ssize offset, int whence)
245 {
246  struct st_filesystem *fs;
247  int rtn = 0;
248 
249  DTFPRINTF(0x02, "fd = %d, offset = %d, whence = %d\n", fd, offset, whence);
250 
251  fs = file_desc[fd].fs;
252  if(fs == 0) {
253  return -1;
254  }
255 
256  if(fs->seek != 0) {
257  rtn = fs->seek(file_desc[fd].fs_desc, offset, whence);
258  }
259 
260  return rtn;
261 }
262 
263 /**
264  @brief ファイルアクセス位置の取得
265 
266  @param[in] fd ファイルディスクリプタ
267 
268  @return 先頭からのオフセット位置バイト数
269 */
270 t_size tell_file(int fd)
271 {
272  struct st_filesystem *fs;
273  int rtn = 0;
274 
275  DTFPRINTF(0x01, "fd = %d\n", fd);
276 
277  fs = file_desc[fd].fs;
278  if(fs == 0) {
279  return -1;
280  }
281 
282  if(fs->tell != 0) {
283  rtn = fs->tell(file_desc[fd].fs_desc);
284  }
285 
286  return rtn;
287 }
288 
289 
290 /**
291  @brief ファイルを閉じる
292 
293  @param[in] fd ファイルディスクリプタ
294 
295  @return 0:成功
296 */
297 int close_file(int fd)
298 {
299  struct st_filesystem *fs;
300  int rtn = 0;
301 
302  DTFPRINTF(0x01, "fd = %d\n", fd);
303 
304  fs = file_desc[fd].fs;
305  if(fs == 0) {
306  return -1;
307  }
308 
309  if(fs->close != 0) {
310  rtn = fs->close(file_desc[fd].fs_desc);
311  }
312 
313  file_desc[fd].flg_used = 0;
314 
315  if(rtn != 0) {
316  SYSERR_PRINT("cannot close file (%d)\n", fd);
317  }
318 
319  return rtn;
320 }
321 
322 /**
323  @brief ディレクトリを開く
324 
325  @param[in] name ディレクトリ名
326 
327  @return ディレクトリ(0:エラー)
328 */
329 FS_DIR * opendir_file(const uchar *name)
330 {
331  struct st_filesystem *fs;
332  FS_DIR *dir = 0;
333 
334  DTFPRINTF(0x01, "dir = %p, name = %s\n", dir, name);
335 
336  fs = get_filesystem(name);
337  if(fs == 0) {
338  return 0;
339  }
340 
341  if(fs->opendir != 0) {
342  dir = fs->opendir(name);
343  }
344 
345  return dir;
346 }
347 
348 /**
349  @brief ディレクトリを読み出す
350 
351  @param[in] dir ディレクトリ
352  @param[out] info ファイル情報
353 
354  @return エラーコード
355 */
356 int readdir_file(FS_DIR *dir, FS_FILEINFO *finfo)
357 {
358  struct st_filesystem *fs;
359  int rtn = 0;
360 
361  DTFPRINTF(0x02, "dir = %p, info = %p\n", dir, finfo);
362 
363  fs = dir->fs;
364  if(fs == 0) {
365  return -1;
366  }
367 
368  if(fs->readdir != 0) {
369  rtn = fs->readdir(dir, finfo);
370  }
371 
372  return rtn;
373 }
374 
375 /**
376  @brief ディレクトリを閉じる
377 
378  @param[in] dir ディレクトリ
379 
380  @return エラーコード
381 */
383 {
384  struct st_filesystem *fs;
385  int rtn = 0;
386 
387  DTFPRINTF(0x01, "dir = %p\n", dir);
388 
389  fs = dir->fs;
390  if(fs == 0) {
391  return -1;
392  }
393 
394  if(fs->closedir != 0) {
395  rtn = fs->closedir(dir);
396  }
397 
398  return rtn;
399 }
400 
401 /**
402  @brief ファイルステータスを読み出す
403 
404  @param[in] path ファイル(ディレクトリ)名
405  @param[out] info ファイル情報構造体ポインタ
406 
407  @return エラーコード
408 */
409 int stat_file(const uchar *path, FS_FILEINFO *finfo)
410 {
411  struct st_filesystem *fs;
412  int rtn = 0;
413 
414  DTFPRINTF(0x02, "path = %s, info = %p\n", path, finfo);
415 
416  fs = get_filesystem(path);
417  if(fs == 0) {
418  return -1;
419  }
420 
421  if(fs->stat != 0) {
422  rtn = fs->stat(path, finfo);
423  }
424 
425  return rtn;
426 }
427 
428 /**
429  @brief 論理ドライブの未使用クラスタ数を取得する
430 
431  @param[in] path ファイル(ドライブ)名
432  @param[out] sect
433  @param[out] fs
434 
435  @return エラーコード
436 */
437 int getfree_file(const uchar *path, unsigned long *sect, void **fso)
438 {
439  struct st_filesystem *fs;
440  int rtn = -1;
441 
442  DTFPRINTF(0x02, "path = %s, sect = %p, fs = %p\n", path, sect, fso);
443 
444  fs = get_filesystem(path);
445  if(fs == 0) {
446  return -1;
447  }
448 
449  if(fs->getfree != 0) {
450  rtn = fs->getfree(path, sect, fso);
451  }
452 
453  return rtn;
454 }
455 
456 /**
457  @brief キャッシュされたデータをフラッシュする
458 
459  @param[in] fd ファイルディスクリプタ
460 
461  @return エラーコード
462 */
463 int sync_file(int fd)
464 {
465  struct st_filesystem *fs;
466  int rtn = 0;
467 
468  DTFPRINTF(0x01, "fd = %d\n", fd);
469 
470  fs = file_desc[fd].fs;
471  if(fs == 0) {
472  return -1;
473  }
474 
475  if(fs->sync != 0) {
476  rtn = fs->sync(file_desc[fd].fs_desc);
477  }
478 
479  return rtn;
480 }
481 
482 /**
483  @brief ファイルを消去する
484 
485  @param[in] path ファイル名
486 
487  @return エラーコード
488 */
489 int unlink_file(const uchar *path)
490 {
491  struct st_filesystem *fs;
492  int rtn = 0;
493 
494  DTFPRINTF(0x02, "path = %s\n", path);
495 
496  fs = get_filesystem(path);
497  if(fs == 0) {
498  return -1;
499  }
500 
501  if(fs->unlink != 0) {
502  rtn = fs->unlink(path);
503  }
504 
505  return rtn;
506 }
507 
508 /**
509  @brief ディレクトリを作成する
510 
511  @param[in] path ディレクトリ名
512 
513  @return エラーコード
514 */
515 int mkdir_file(const uchar *path)
516 {
517  struct st_filesystem *fs;
518  int rtn = 0;
519 
520  DTFPRINTF(0x02, "path = %s\n", path);
521 
522  fs = get_filesystem(path);
523  if(fs == 0) {
524  return -1;
525  }
526 
527  if(fs->mkdir != 0) {
528  rtn = fs->mkdir(path);
529  }
530 
531  return rtn;
532 }
533 
534 #if FF_USE_CHMOD != 0
535 /**
536  @brief ファイルまたはディレクとの属性を変更する
537 
538  @param[in] path ファイルまたはディレクトリ名
539  @param[in] flag 設定する属性
540 
541  @return エラーコード
542 */
543 int chmod_file(const uchar *path, unsigned char flag)
544 {
545  struct st_filesystem *fs;
546  int rtn = 0;
547 
548  DTFPRINTF(0x02, "path = %s, flag = %d\n", path, flag);
549 
550  fs = get_filesystem(path);
551  if(fs == 0) {
552  return -1;
553  }
554 
555  if(fs->chmod != 0) {
556  rtn = fs->chmod(path, flag);
557  }
558 
559  return rtn;
560 }
561 #endif
562 
563 /**
564  @brief ファイル/ディレクトリ名を変更する
565 
566  @param[in] oldpath 変更されるファイル名
567  @param[in] newpath 変更後のファイル名
568 
569  @return エラーコード
570 
571  @info 異なるデバイスへの名前変更はできない
572 */
573 int rename_file(const uchar *oldpath, const uchar *newpath)
574 {
575  struct st_filesystem *fs;
576  int rtn = 0;
577 
578  DTFPRINTF(0x02, "oldpath = %s, newpath = %s\n", oldpath, newpath);
579 
580  fs = get_filesystem(oldpath);
581  if(fs == 0) {
582  return -1;
583  }
584 
585  if(fs->rename != 0) {
586  rtn = fs->rename(oldpath, newpath);
587  }
588 
589  return rtn;
590 }
591 
592 #if FF_USE_MKFS != 0
593 /**
594  @brief ディスクをフォーマットする
595 
596  @param[in] drive 論理ドライブ番号
597  @param[in] part
598  @param[in] alloc クラスタサイズ
599 
600  @return エラーコード
601 
602  @todo ディスクフォーマット機能
603 */
604 int mkfs_file(const uchar *path, unsigned char part, unsigned short alloc)
605 {
606  struct st_filesystem *fs;
607  int rtn = 0;
608 
609  DTFPRINTF(0x02, "path = %s, part = %d, alloc = %d\n", ath, part, alloc);
610 
611  fs = get_filesystem(path);
612  if(fs == 0) {
613  return -1;
614  }
615 
616  if(fs->mkfs != 0) {
617  rtn = fs->mkfs(path, part, alloc);
618  }
619 
620  return rtn;
621 }
622 #endif
623 
624 /**
625  @brief ファイルパスからファイル名のみを取得する
626 
627  @param[out] filename ファイル名
628  @param[in] fullpath ファイルパス名
629  @param[in] len 最大ファイル名バイト数
630 
631  @return ファイル名
632 */
633 uchar * get_last_filename(uchar *filename, const uchar *fullpath, unsigned int len)
634 {
635  uchar *p;
636 
637  if(filename == 0) {
638  return 0;
639  }
640 
641  if(fullpath == 0) {
642  return 0;
643  }
644 
645  if(*fullpath == 0) {
646  return 0;
647  }
648 
649  p = (uchar *)fullpath + strleng(fullpath) - 1;
650 
651  while((*p) != 0) {
652  if((*p == '\\') || *p == '/') {
653  if(filename != 0) {
654  if(filename != 0) {
655  (void)strncopy(filename, p+1, len);
656  }
657  }
658  return p+1;
659  }
660  p--;
661  }
662 
663  return 0;
664 }
665 
666 
667 /**
668  @brief ファイル拡張子を取得する
669 
670  @param[out] 拡張子文字列
671  @param[in] ファイル名
672  @param[in] 最大拡張子文字列バイト数
673 
674  @return 拡張子文字列
675 */
676 uchar * get_filename_extension(uchar *ext, const uchar *filename, unsigned int len)
677 {
678  uchar *p;
679 
680  if(filename == 0) {
681  return 0;
682  }
683 
684  if(*filename == 0) {
685  return 0;
686  }
687 
688  p = (uchar *)filename + strleng(filename) - 1;
689 
690  while((*p) != 0) {
691  if(*p == '.') {
692  if(ext != 0) {
693  if(ext != 0) {
694  (void)strncopy(ext, p+1, len);
695  }
696  }
697  return p+1;
698  }
699  p--;
700  }
701 
702  return 0;
703 }
704 
705 char * size2str(char *str, t_size size)
706 {
707  t_size size_g = (1024L*1024*1024L);
708  t_size size_m = (1024L*1024);
709  t_size size_k = 1024L;
710 
711  if(size >= size_g) {
712  if((size/size_g) < 10) {
713  tsnprintf(str, SIZE_STR_LEN, "%1d.%1dG", (int)(size/size_g), (int)((size-((size/size_g))*size_g))/1024/1024/100);
714  } else {
715  tsnprintf(str, SIZE_STR_LEN, "%3dG", (int)(size/size_g));
716  }
717  } else if(size >= size_m) {
718  if((size/size_m) < 10) {
719  tsnprintf(str, SIZE_STR_LEN, "%1d.%1dM", (int)(size/size_m), (int)((size-((size/size_m))*size_m))/1024/100);
720  } else {
721  tsnprintf(str, SIZE_STR_LEN, "%3dM", (int)(size/size_m));
722  }
723  } else if(size >= size_k) {
724  if((size/size_k) < 10) {
725  tsnprintf(str, SIZE_STR_LEN, "%1d.%1dK", (int)(size/size_k), (int)((size-((size/size_k))*size_k))/100);
726  } else {
727  tsnprintf(str, SIZE_STR_LEN, "%3dK", (int)(size/size_k));
728  }
729  } else {
730  tsnprintf(str, SIZE_STR_LEN, "%3dB", (int)size);
731  }
732 
733  return &str[0];
734 }
unsigned char uchar
GadgetSeedの文字(列)は unsigned char 型となる
Definition: str.h:13
t_ssize seek_file(int fd, t_ssize offset, int whence)
ファイルアクセス位置の設定
Definition: file.c:244
t_ssize write_file(int fd, const void *buf, t_size count)
ファイルにデータを書き込む
Definition: file.c:216
t_ssize read_file(int fd, void *buf, t_size count)
ファイルからデータを読み出す
Definition: file.c:188
ファイルシステム構造体
Definition: fs.h:56
Definition: fs.h:44
t_size tell_file(int fd)
ファイルアクセス位置の取得
Definition: file.c:270
int unlink_file(const uchar *path)
ファイルを消去する
Definition: file.c:489
int closedir_file(FS_DIR *dir)
ディレクトリを閉じる
Definition: file.c:382
アプリケーション(タスク)デバッグ用マクロ
FS_DIR * opendir_file(const uchar *name)
ディレクトリを開く
Definition: file.c:329
ファイルシステムAPI
struct st_filesystem * get_filesystem(const uchar *path)
ファイル名からファイルシステムを調べる
Definition: file.c:120
文字列処理
ファイル
int stat_file(const uchar *path, FS_FILEINFO *finfo)
ファイルステータスを読み出す
Definition: file.c:409
int rename_file(const uchar *oldpath, const uchar *newpath)
ファイル/ディレクトリ名を変更する
Definition: file.c:573
カーネル用機能限定printf
int getfree_file(const uchar *path, unsigned long *sect, void **fso)
論理ドライブの未使用クラスタ数を取得する
Definition: file.c:437
int mkdir_file(const uchar *path)
ディレクトリを作成する
Definition: file.c:515
struct st_storage_info storage[GSC_FS_VOLUME_NUM]
ストレージデバイステーブル
Definition: storage.c:39
int close_file(int fd)
ファイルを閉じる
Definition: file.c:297
int get_diskno(const uchar *path)
ファイル名からストレージ番号を調べる
Definition: file.c:100
unsigned int strleng(const uchar *str)
文字列長
Definition: str.c:657
外部記憶装置管理
ストレージデバイス
Definition: storage.h:18
void init_file(void)
全てのファイルディスクリプタを初期化する
Definition: file.c:84
uchar * get_filename_extension(uchar *ext, const uchar *filename, unsigned int len)
ファイル拡張子を取得する
Definition: file.c:676
int readdir_file(FS_DIR *dir, FS_FILEINFO *finfo)
ディレクトリを読み出す
Definition: file.c:356
Definition: fs.h:37
#define GSC_FS_VOLUME_NUM
$gsc 最大ストレージデバイスボリューム数
Definition: storage.h:15
uchar * strncopy(uchar *dest, const uchar *src, unsigned int n)
文字列コピー
Definition: str.c:632
デバイスドライバAPI
int open_file(const uchar *path, int flags)
ファイルを開く
Definition: file.c:144
int sync_file(int fd)
キャッシュされたデータをフラッシュする
Definition: file.c:463
uchar * get_last_filename(uchar *filename, const uchar *fullpath, unsigned int len)
ファイルパスからファイル名のみを取得する
Definition: file.c:633
#define GSC_FS_MAX_FILE_NUM
$gsc オープンできる最大ファイル数
Definition: file.c:69
int tsnprintf(char *str, unsigned int size, const char *fmt,...)
簡易snprintf
Definition: tprintf.c:60