1. Directory opreations:
[lwext4.git] / demos / generic / main.c
1 /*\r
2  * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions\r
7  * are met:\r
8  *\r
9  * - Redistributions of source code must retain the above copyright\r
10  *   notice, this list of conditions and the following disclaimer.\r
11  * - Redistributions in binary form must reproduce the above copyright\r
12  *   notice, this list of conditions and the following disclaimer in the\r
13  *   documentation and/or other materials provided with the distribution.\r
14  * - The name of the author may not be used to endorse or promote products\r
15  *   derived from this software without specific prior written permission.\r
16  *\r
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  */\r
28 \r
29 #include <stdio.h>\r
30 #include <stdlib.h>\r
31 #include <string.h>\r
32 #include <unistd.h>\r
33 #include <getopt.h>\r
34 #include <stdbool.h>\r
35 \r
36 #include <ext4_filedev.h>\r
37 #include <ext4.h>\r
38 \r
39 \r
40 \r
41 char input_name[128] = "ext2";\r
42 \r
43 /**@brief       Read-write size*/\r
44 static int rw_szie  = 1024;\r
45 \r
46 /**@brief       Read-write size*/\r
47 static int rw_count = 1024;\r
48 \r
49 /**@brief   Directory test count*/\r
50 static int dir_cnt  = 10;\r
51 \r
52 static bool cache_mode = false;\r
53 \r
54 \r
55 /**@brief       File write buffer*/\r
56 static uint8_t  *wr_buff;\r
57 \r
58 /**@brief       File read buffer.*/\r
59 static uint8_t  *rd_buff;\r
60 \r
61 /**@brief       Block device handle.*/\r
62 static struct ext4_blockdev *bd;\r
63 \r
64 /**@brief       Block cache handle.*/\r
65 static struct ext4_bcache   *bc;\r
66 \r
67 static const char *usage = "                                                                    \n\\r
68 Welcome in ext4 generic demo.                                                                   \n\\r
69 Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)  \n\\r
70 Usage:                                                                                                                  \n\\r
71         -i   - input file             (default = ext2)                          \n\\r
72         -rws - single R/W size        (default = 1024)                          \n\\r
73         -rwc - R/W count              (default = 1024)                          \n\\r
74         -cache - 0 static, 1 dynamic  (default = 0)                                     \n\\r
75     -dirs  - directory test count (default = 0)                 \n\\r
76 \n";\r
77 \r
78 static char* entry_to_str(uint8_t type)\r
79 {\r
80         switch(type){\r
81         case EXT4_DIRENTRY_UNKNOWN:\r
82                 return "[UNK] ";\r
83         case EXT4_DIRENTRY_REG_FILE:\r
84                 return "[FIL] ";\r
85         case EXT4_DIRENTRY_DIR:\r
86                 return "[DIR] ";\r
87         case EXT4_DIRENTRY_CHRDEV:\r
88                 return "[CHA] ";\r
89         case EXT4_DIRENTRY_BLKDEV:\r
90                 return "[BLK] ";\r
91         case EXT4_DIRENTRY_FIFO:\r
92                 return "[FIF] ";\r
93         case EXT4_DIRENTRY_SOCK:\r
94                 return "[SOC] ";\r
95         case EXT4_DIRENTRY_SYMLINK:\r
96                 return "[SYM] ";\r
97         default:\r
98                 break;\r
99         }\r
100         return "[???]";\r
101 }\r
102 \r
103 static void dir_ls(const char *path)\r
104 {\r
105         int j = 0;\r
106         char sss[255];\r
107         ext4_dir d;\r
108         ext4_direntry *de;\r
109 \r
110         printf("**********************************************\n");\r
111 \r
112         ext4_dir_open(&d, path);\r
113         de = ext4_dir_entry_get(&d, j++);\r
114         printf("ls %s\n", path);\r
115 \r
116         while(de){\r
117                 memcpy(sss, de->name, de->name_length);\r
118                 sss[de->name_length] = 0;\r
119                 printf(entry_to_str(de->inode_type));\r
120                 printf(sss);\r
121                 printf("\n");\r
122                 de = ext4_dir_entry_get(&d, j++);\r
123         }\r
124         printf("**********************************************\n");\r
125         ext4_dir_close(&d);\r
126 }\r
127 \r
128 static void mp_stats(void)\r
129 {\r
130     struct ext4_mount_stats stats;\r
131     ext4_mount_point_stats("/mp/", &stats);\r
132 \r
133     printf("**********************************************\n");\r
134     printf("ext4_mount_point_stats\n");\r
135     printf("inodes_count        = %u\n", stats.inodes_count);\r
136     printf("free_inodes_count   = %u\n", stats.free_inodes_count);\r
137     printf("blocks_count        = %u\n", (uint32_t)stats.blocks_count);\r
138     printf("free_blocks_count   = %u\n", (uint32_t)stats.free_blocks_count);\r
139     printf("block_size          = %u\n", stats.block_size);\r
140     printf("block_group_count   = %u\n", stats.block_group_count);\r
141     printf("blocks_per_group    = %u\n", stats.blocks_per_group);\r
142     printf("inodes_per_group    = %u\n", stats.inodes_per_group);\r
143     printf("volume_name         = %s\n", stats.volume_name);\r
144 \r
145     printf("**********************************************\n");\r
146 \r
147 }\r
148 \r
149 static void block_stats(void)\r
150 {\r
151     uint32_t i;\r
152 \r
153     printf("**********************************************\n");\r
154     printf("ext4 blockdev stats\n");\r
155     printf("bdev->bread_ctr          = %u\n", bd->bread_ctr);\r
156     printf("bdev->bwrite_ctr         = %u\n", bd->bwrite_ctr);\r
157 \r
158 \r
159     printf("bcache->ref_blocks       = %u\n", bc->ref_blocks);\r
160     printf("bcache->max_ref_blocks   = %u\n", bc->max_ref_blocks);\r
161     printf("bcache->lru_ctr          = %u\n", bc->lru_ctr);\r
162 \r
163     printf("\n");\r
164     for (i = 0; i < bc->cnt; ++i) {\r
165         printf("bcache->refctr[%d]     = %u\n", i, bc->refctr[i]);\r
166     }\r
167 \r
168     printf("\n");\r
169     for (i = 0; i < bc->cnt; ++i) {\r
170         printf("bcache->lru_id[%d]     = %u\n", i, bc->lru_id[i]);\r
171     }\r
172 \r
173     printf("\n");\r
174     for (i = 0; i < bc->cnt; ++i) {\r
175         printf("bcache->free_delay[%d] = %d\n", i, bc->free_delay[i]);\r
176     }\r
177 \r
178     printf("\n");\r
179     for (i = 0; i < bc->cnt; ++i) {\r
180         printf("bcache->lba[%d]        = %u\n", i, (uint32_t)bc->lba[i]);\r
181     }\r
182 \r
183 \r
184 \r
185     printf("**********************************************\n");\r
186 }\r
187 \r
188 static bool dir_test(int len)\r
189 {\r
190     ext4_file f;\r
191     int       r;\r
192     int       i;\r
193     char path[64];\r
194 \r
195     printf("Remove directory /mp/dir1\n");\r
196     ext4_dir_rm("/mp/dir1");\r
197 \r
198 \r
199     printf("Directory create: /mp/dir1\n");\r
200     r = ext4_dir_mk("/mp/dir1");\r
201     if(r != EOK){\r
202         printf("Unable to create directory: /mp/dir1\n");\r
203         return false;\r
204     }\r
205 \r
206 \r
207     printf("Add files to: /mp/dir1\n");\r
208     for (i = 0; i < len; ++i) {\r
209         sprintf(path, "/mp/dir1/f%d", i);\r
210         r = ext4_fopen(&f, path, "wb");\r
211         if(r != EOK){\r
212             printf("Unable to create file in directory: /mp/dir1\n");\r
213             return false;\r
214         }\r
215     }\r
216 \r
217     printf("Add directories to: /mp/dir1\n");\r
218     for (i = 0; i < len; ++i) {\r
219         sprintf(path, "/mp/dir1/d%d", i);\r
220         r = ext4_dir_mk(path);\r
221         if(r != EOK){\r
222             printf("Unable to create directory in directory: /mp/dir1\n");\r
223             return false;\r
224         }\r
225     }\r
226 \r
227     printf("Add file directories in: /mp/dir1\n");\r
228 \r
229     for (i = 0; i < len; ++i) {\r
230         sprintf(path, "/mp/dir1/d%d/ff", i);\r
231         r = ext4_fopen(&f, path, "wb");\r
232         if(r != EOK){\r
233             printf("Unable to create file in directory: /mp/dir1\n");\r
234             return false;\r
235         }\r
236     }\r
237 \r
238     dir_ls("/mp/dir1");\r
239     return true;\r
240 }\r
241 \r
242 int main(int argc, char **argv)\r
243 {\r
244         int option_index = 0;\r
245         int     c;\r
246         int     r;\r
247         int     i;\r
248         uint32_t  size;\r
249         ext4_file f;\r
250 \r
251     static struct option long_options[] =\r
252       {\r
253         {"in",          required_argument, 0, 'a'},\r
254         {"rws",     required_argument, 0, 'b'},\r
255         {"rwc",         required_argument, 0, 'c'},\r
256         {"cache",   required_argument, 0, 'd'},\r
257         {"dirs",   required_argument,  0, 'e'},\r
258         {0, 0, 0, 0}\r
259       };\r
260 \r
261     while(-1 != (c = getopt_long (argc, argv, "a:b:c:d:e:", long_options, &option_index))) {\r
262 \r
263         switch(c){\r
264                 case 'a':\r
265                         strcpy(input_name, optarg);\r
266                         break;\r
267                 case 'b':\r
268                         rw_szie = atoi(optarg);\r
269                         break;\r
270                 case 'c':\r
271                         rw_count = atoi(optarg);\r
272                         break;\r
273                 case 'd':\r
274                         cache_mode = atoi(optarg);\r
275                         break;\r
276             case 'e':\r
277                 dir_cnt = atoi(optarg);\r
278                 break;\r
279                 default:\r
280                         printf(usage);\r
281                         return EXIT_FAILURE;\r
282 \r
283         }\r
284     }\r
285 \r
286     printf("Test conditions:\n");\r
287     printf("Imput name: %s\n", input_name);\r
288     printf("RW size: %d\n",  rw_szie);\r
289     printf("RW count: %d\n", rw_count);\r
290     printf("Cache mode: %s\n", cache_mode ? "dynamic" : "static");\r
291 \r
292 \r
293 \r
294     ext4_filedev_filename(input_name);\r
295 \r
296     wr_buff = malloc(rw_szie);\r
297     rd_buff = malloc(rw_szie);\r
298 \r
299     if(!wr_buff || !rd_buff){\r
300         printf("Read-Write allocation ERROR\n");\r
301         return EXIT_FAILURE;\r
302     }\r
303 \r
304         bd = ext4_filedev_get();\r
305         bc = ext4_filecache_get();\r
306 \r
307     if(!bd || !bc){\r
308         printf("Block device ERROR\n");\r
309         return EXIT_FAILURE;\r
310     }\r
311 \r
312         ext4_dmask_set(EXT4_DEBUG_ALL);\r
313 \r
314         r = ext4_device_register(bd, cache_mode ? 0 : bc, "ext4_filesim");\r
315         if(r != EOK){\r
316                 printf("ext4_device_register ERROR = %d\n", r);\r
317                 return EXIT_FAILURE;\r
318         }\r
319 \r
320         r = ext4_mount("ext4_filesim", "/mp/");\r
321         if(r != EOK){\r
322                 printf("ext4_mount ERROR = %d\n", r);\r
323                 return EXIT_FAILURE;\r
324         }\r
325 \r
326         dir_test(dir_cnt);\r
327 \r
328         ext4_fremove("/mp/hello.txt");\r
329         ext4_fremove("/mp/test1");\r
330         mp_stats();\r
331         dir_ls("/mp/");\r
332 \r
333     /*Add hello world file.*/\r
334     r = ext4_fopen(&f, "/mp/hello.txt", "wb");\r
335     r = ext4_fwrite(&f, "Hello World !\n", strlen("Hello World !\n"), 0);\r
336     r = ext4_fclose(&f);\r
337 \r
338 \r
339         printf("ext4_fopen: test1\n");\r
340 \r
341         r = ext4_fopen(&f, "/mp/test1", "wb");\r
342         if(r != EOK){\r
343                 printf("ext4_fopen ERROR = %d\n", r);\r
344                 return EXIT_FAILURE;\r
345         }\r
346 \r
347         printf("ext4_write: %d * %d ..." , rw_count, rw_szie);\r
348 \r
349         for (i = 0; i < rw_count; ++i) {\r
350 \r
351                 memset(wr_buff, i & 0xFF, rw_szie);\r
352 \r
353                 r = ext4_fwrite(&f, wr_buff, rw_szie, &size);\r
354 \r
355                 if((r != EOK) || (size != rw_szie))\r
356                         break;\r
357         }\r
358 \r
359         if(i != rw_count){\r
360                 printf("ERROR: rw_count = %d\n", i);\r
361                 return EXIT_FAILURE;\r
362         }\r
363 \r
364         printf("OK\n");\r
365         r = ext4_fclose(&f);\r
366         printf("ext4_fopen: test1\n");\r
367 \r
368         r = ext4_fopen(&f, "/mp/test1", "r+");\r
369         if(r != EOK){\r
370                 printf("ext4_fopen ERROR = %d\n", r);\r
371                 return EXIT_FAILURE;\r
372         }\r
373 \r
374         printf("ext4_read: %d * %d ..." , rw_count, rw_szie);\r
375 \r
376         for (i = 0; i < rw_count; ++i) {\r
377                 memset(wr_buff, i & 0xFF, rw_szie);\r
378                 r = ext4_fread(&f, rd_buff, rw_szie, &size);\r
379 \r
380                 if((r != EOK) || (size != rw_szie))\r
381                         break;\r
382 \r
383                 if(memcmp(rd_buff, wr_buff, rw_szie)){\r
384                         break;\r
385                 }\r
386         }\r
387         if(i != rw_count){\r
388                 printf("ERROR: rw_count = %d\n", i);\r
389                 return EXIT_FAILURE;\r
390         }\r
391 \r
392         printf("OK\n");\r
393 \r
394         r = ext4_fclose(&f);\r
395 \r
396 \r
397         mp_stats();\r
398         dir_ls("/mp/");\r
399 \r
400         block_stats();\r
401         r = ext4_umount("/mp/");\r
402 \r
403         printf("Test finish: OK\n");\r
404     return EXIT_SUCCESS;\r
405 \r
406 }\r