load modules common to all linux revisions
[cinitramfs.git] / ramfs.c
blob6d142befdbc559aa3b6089443a2988b054bc71de
1 /*******************************************************************************
2 this code is protected by the GNU affero GPLv3
3 author:Sylvain BERTRAND <sylvain.bertrand AT gmail dot com>
4 *******************************************************************************/
5 #include <ulinux/compiler_types.h>
6 #include <ulinux/types.h>
7 #include <ulinux/error.h>
8 #include <ulinux/fs.h>
9 #include <ulinux/file.h>
10 #include <ulinux/dirent.h>
11 #include <ulinux/utils/mem.h>
12 #include <ulinux/utils/ascii/string/string.h>
13 #include <ulinux/sysc.h>
15 #include "out.h"
16 #include "ulinux_namespace.h"
17 #include "globals.h"
19 #define DIRENTS_BUF_SZ 8192
21 static u8 is_current(u8 *n)
23 if(n[0]=='.'&&n[1]==0) return 1;
24 return 0;
27 static u8 is_parent(u8 *n)
29 if(n[0]=='.'&&n[1]=='.'&&n[2]==0) return 1;
30 return 0;
33 static u8 is_newroot(u8 *n)
35 #define NEWROOT (u8*)"newroot"
36 return strncmp(n,NEWROOT,sizeof(NEWROOT)-1)?0:1;
39 static void unlink(i parent_fd,u8 *n,i flgs)
41 l r=unlinkat(parent_fd,n,flgs);
42 if(ISERR(r)){
43 OUT("ERROR(%ld):unable to remove dir entry:%s\n",r,n);
44 exit_group(-1);
48 static void dir_del(i parent_fd);
49 static void dirent_del(i parent_fd,struct dirent64 *d)
51 if(d->type==DT_DIR){
52 if(!is_current(d->name)&&!is_parent(d->name)){
53 i dir_fd;
54 loop{
55 dir_fd=(i)openat(parent_fd,d->name,ULINUX_O_RDONLY|ULINUX_O_NONBLOCK);
56 if(dir_fd!=-EINTR) break;
58 if(ISERR(dir_fd)){
59 OUT("ERROR(%d):unable to open subdir:%s\n",dir_fd,d->name);
60 exit_group(-1);
61 }else{
62 l r;
63 dir_del(dir_fd);
64 loop{
65 r=close(dir_fd);
66 if(r!=-EINTR) break;
68 if(ISERR(r)){
69 OUT("ERROR(%ld):unable to close dir fd\n",r);
70 exit_group(-1);
73 unlink(parent_fd,d->name,AT_REMOVEDIR);
75 }else unlink(parent_fd,d->name,0);
78 static void dir_del(i parent_fd)
80 u8 dirents[DIRENTS_BUF_SZ];
81 loop{
82 l idx;
83 l r=getdents64(parent_fd,dirents,DIRENTS_BUF_SZ);
84 if(ISERR(r)){
85 OUT("ERROR(%ld):getdents error\n",r);
86 exit_group(-1);
89 if(!r) break;
91 idx=0;
92 loop{
93 struct dirent64 *d;
95 if(idx>=r) break;
96 d=(struct dirent64*)(dirents+idx);
97 dirent_del(parent_fd,d);
98 idx+=d->rec_len;
103 void ramfs_cleanup(void)
105 OUT(PRE "cleaning ramfs...");
106 i root_fd;
107 loop{
108 root_fd=(i)open("/",ULINUX_O_RDONLY|ULINUX_O_NONBLOCK);
109 if(root_fd!=-EINTR) break;
111 if(ISERR(root_fd)){
112 OUT("ERROR(%d):unable to open root dir\n",root_fd);
113 exit_group(-1);
116 u8 dirents[DIRENTS_BUF_SZ];
117 loop{
118 l idx;
119 l r=getdents64(root_fd,dirents,DIRENTS_BUF_SZ);
120 if(ISERR(r)){
121 OUT("ERROR(%ld):getdents error\n",r);
122 exit_group(-1);
125 if(!r) break;/*empty*/
127 idx=0;
128 loop{
129 struct dirent64 *d;
131 if(idx>=r) break;
133 d=(struct dirent64*)(dirents+idx);
134 if(!is_newroot(d->name)) dirent_del(root_fd,d);
135 idx+=d->rec_len;
138 l r;
139 loop{
140 r=close(root_fd);
141 if(r!=-EINTR) break;
143 if(ISERR(r)){
144 OUT("ERROR(%ld):unable to root dir fd\n",r);
145 exit_group(-1);
147 OUT("done\n");