2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
30 #define PROCFS_NAME "procfs"
31 #define PROCFS_MOUNTPOINT "/proc"
33 typedef struct procfs_path_S procfs_path_t
;
53 int (*cb_read
)(procfs_path_t
*path
,char *buf
,size_t size
,off_t offset
);
54 int (*cb_write
)(procfs_path_t
*path
,const char *buf
,size_t size
,off_t offset
);
57 int (*cb_readdir
)(procfs_path_t
*path
,void *buf
,fuse_fill_dir_t filler
,off_t offset
);
63 struct procfs_path_S
{
71 static int procfs_loginuid_read(procfs_path_t
*path
,char *buf
,size_t size
,off_t offset
);
72 static int procfs_mem_read(procfs_path_t
*path
,char *buf
,size_t size
,off_t offset
);
73 static int procfs_mem_write(procfs_path_t
*path
,const char *buf
,size_t size
,off_t offset
);
74 static procfs_file_t procfs_files
[] = {
75 { .name
= "cwd", .ftype
= PROCFS_SYMLINK
},
76 { .name
= "exe", .ftype
= PROCFS_SYMLINK
},
77 { .name
= "loginuid", .ftype
= PROCFS_FILE
, .file
= { .cb_read
= procfs_loginuid_read
} },
78 { .name
= "mem", .ftype
= PROCFS_FILE
, .file
= { .cb_read
= procfs_mem_read
, .cb_write
= procfs_mem_write
} },
82 static llist_t procfs_processes
;
84 static int procfs_loginuid_read(procfs_path_t
*path
,char *buf
,size_t size
,off_t offset
) {
88 static int procfs_mem_read(procfs_path_t
*path
,char *buf
,size_t size
,off_t offset
) {
92 static int procfs_mem_write(procfs_path_t
*path
,const char *buf
,size_t size
,off_t offset
) {
96 static procfs_proc_t
*procfs_proc_find(pid_t pid
) {
99 for (i
=0;(proc
= llist_get(procfs_processes
,i
));i
++) {
100 if (proc
->pid
==pid
) return proc
;
105 int procfs_proc_new(pid_t pid
,const char *name
,const char *exe
) {
106 procfs_proc_t
*proc
= malloc(sizeof(procfs_proc_t
));
108 proc
->uid
= getuidbypid(pid
);
109 proc
->gid
= getgidbypid(pid
);
110 if (name
==NULL
) proc
->name
= getname(pid
);
111 else proc
->name
= strdup(name
);
112 if (exe
==NULL
) proc
->exe
= NULL
;
113 else proc
->exe
= strdup(exe
);
114 llist_push(procfs_processes
,proc
);
118 int procfs_proc_update(pid_t pid
,const char *name
,const char *exe
) {
119 procfs_proc_t
*proc
= procfs_proc_find(pid
);
123 proc
->name
= strdup(name
);
127 proc
->exe
= strdup(exe
);
134 static void procfs_parse_path(const char *strpath
,procfs_path_t
*path
) {
135 path_t
*tpath
= path_parse(strpath
);
136 path_reject_dots(tpath
);
138 memset(path
,0,sizeof(procfs_path_t
));
140 if (tpath
->num_parts
>0) {
141 path
->pid
= strtoul(tpath
->parts
[0],NULL
,10);
142 path
->proc
= procfs_proc_find(path
->pid
);
145 if (tpath
->num_parts
>1) {
147 for (i
=0;procfs_files
[i
].name
!=NULL
;i
++) {
148 if (strcmp(tpath
->parts
[1],procfs_files
[i
].name
)==0) {
149 path
->file
= procfs_files
+i
;
150 path
->isdir
= (path
->file
->ftype
==PROCFS_DIR
);
154 if (tpath
->num_parts
>2) {
155 static char subfile_buf
[256];
156 strncpy(subfile_buf
,tpath
->parts
[2],256);
157 path
->subfile
= subfile_buf
;
164 static int procfs_open(const char *strpath
,struct fuse_file_info
*fi
) {
167 if (path
.pid
!=0 && path
.proc
!=NULL
) return -ENOENT
;
168 else if (path
.isdir
) return -EISDIR
;
172 static int procfs_close(const char *path
,struct fuse_file_info
*fi
) {
176 static int procfs_read(const char *strpath
,char *buf
,size_t count
,off_t offset
,struct fuse_file_info
*fi
) {
178 procfs_parse_path(strpath
,&path
);
180 if (path
.pid
!=0 && path
.proc
!=NULL
) return -ENOENT
;
181 else if (path
.isdir
) return -EISDIR
;
183 if (path
.file
->file
.cb_read
!=NULL
) return path
.file
->file
.cb_read(&path
,buf
,count
,offset
);
188 static int procfs_write(const char *strpath
,const char *buf
,size_t count
,off_t offset
,struct fuse_file_info
*fi
) {
190 procfs_parse_path(strpath
,&path
);
192 if (path
.pid
!=0 && path
.proc
!=NULL
) return -ENOENT
;
193 else if (path
.isdir
) return -EISDIR
;
195 if (path
.file
->file
.cb_write
!=NULL
) return path
.file
->file
.cb_write(&path
,buf
,count
,offset
);
200 static int procfs_readdir(const char *strpath
,void *buf
,fuse_fill_dir_t filler
,off_t offset
,struct fuse_file_info
*fi
) {
202 procfs_parse_path(strpath
,&path
);
204 if (!path
.isdir
) return -ENOTDIR
;
205 else if (path
.pid
==0) {
206 // list all processes
209 struct stat stbuf
= {
210 /// @todo correct permissions
211 .st_mode
= S_IFDIR
|0777,
213 for (i
=0;(proc
= llist_get(procfs_processes
,i
));i
++) {
215 snprintf(str_pid
,16,"%d",proc
->pid
);
216 stbuf
.st_uid
= proc
->uid
;
217 stbuf
.st_gid
= proc
->gid
;
218 filler(buf
,str_pid
,&stbuf
,0);
222 else if (path
.proc
!=NULL
) return -ENOENT
;
224 if (path
.file
->dir
.cb_readdir
!=NULL
) return path
.file
->dir
.cb_readdir(&path
,buf
,filler
,offset
);
229 static int procfs_getattr(const char *strpath
,struct stat
*stbuf
) {
231 procfs_parse_path(strpath
,&path
);
233 memset(stbuf
,0,sizeof(struct stat
));
235 if (path
.file
!=NULL
) {
236 if (path
.file
->ftype
==PROCFS_DIR
) stbuf
->st_mode
= S_IFDIR
;
237 else if (path
.file
->ftype
==PROCFS_SYMLINK
) stbuf
->st_mode
= S_IFLNK
;
238 else stbuf
->st_mode
= S_IFREG
;
240 else stbuf
->st_mode
= S_IFDIR
;
242 /// @todo correct permissions
243 stbuf
->st_mode
|= 0777;
248 int procfs_init(pid_t
*grub_modules
) {
252 procfs_processes
= llist_create();
254 // put init itself in process list
255 procfs_proc_new(1,"init",NULL
);
257 // put GRUB modules in process list
258 for (i
=0;(pid
= grub_modules
[i
])!=0;i
++) {
259 procfs_proc_new(pid
,NULL
,NULL
);
265 int procfs_run(void) {
267 struct fuse_operations devfs_oper
= {
269 .release
= procfs_close
,
271 .write
= procfs_write
,
272 .readdir
= procfs_readdir
,
273 .getattr
= procfs_getattr
278 char *fake_argv
[2] = { PROCFS_NAME
,PROCFS_MOUNTPOINT
};
279 fuse_main(fake_argc
,fake_argv
,&devfs_oper
,NULL
);