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 Lesser 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
33 #include <fcntl.h> // open,close
34 #include <unistd.h> // read,write,seek,truncate
35 #include <dirent.h> // *dir
36 #include <sys/stat.h> // stat
37 #include <sys/statvfs.h> // statvfs
38 #include <utime.h> // utime
40 #include <sys/socket.h> // Socket stuff
42 #define getnew_fh() (lastfh++)
43 #define filebyfh(fh) llist_get(filelist,lidxbyfh(fh))
45 #define SHMMEM_SIZE (2*PAGE_SIZE)
54 struct filelist_item
{
55 struct fslist_item
*fs
;
57 struct dirent dir_cur
;
64 enum { FL_FILE
,FL_DIR
,FL_PIPE
,FL_SOCK
} type
;
65 /// @todo Check for right file types (e.g. in read()/write()) and set them in open()/opendir()/socket()
68 static llist_t filelist
;
69 static llist_t fslist
;
76 static mode_t creation_mask
;
77 struct process_data
*_process_data
;
79 static int _open_unnamed_pipe(int fh
,int shmid
);
82 * Initializes File I/O
85 filelist
= llist_create();
86 fslist
= llist_create();
90 // Init current workdir
91 char *path
= getenv("PATH");
92 if (path
==NULL
) path
= "/";
93 memset(&workdir
,0,sizeof(workdir
));
96 // Create stdin, stdout, stderr
97 _open_unnamed_pipe(STDIN_FILENO
,_process_data
->shmid_stdin
);
98 _open_unnamed_pipe(STDOUT_FILENO
,_process_data
->shmid_stdout
);
99 _open_unnamed_pipe(STDERR_FILENO
,_process_data
->shmid_stderr
);
104 * @param file Path to file
105 * @param parent If FS of parent directory of file is needed
106 * @return FS List item
108 static struct fslist_item
*mp_match(char *file
,int parent
) {
111 struct fslist_item
*fs
;
112 struct fslist_item
*maxfs
= NULL
;
113 path_t
*path
= path_parse(file
);
115 if (parent
) path_parent(path
);
117 for (i
=0;(fs
= llist_get(fslist
,i
));i
++) {
118 curcmp
= path_compare(path
,fs
->mountpoint
);
125 if (maxfs
!=NULL
) memmove(file
,file
+strlen(maxfs
->mountpoint_str
),strlen(file
)-strlen(maxfs
->mountpoint_str
)+1);
126 if (file
[0]==0) strcpy(file
,"/");
132 * Gets FSID and PID by path and cuts path to relative path for FS
133 * @param path Path to file
134 * @param parent If FS of parent directory of file is needed
137 static struct fslist_item
*fsbypath(char *path
,int parent
) {
138 struct fslist_item
*fs
= mp_match(path
,parent
);
140 fs
= malloc(sizeof(struct fslist_item
));
141 char *mountpoint
= strdup(path
);
142 fs
->id
= rpc_call("vfs_getfsid",2,path
,parent
);
148 mountpoint
[strlen(mountpoint
)-strlen(path
)] = 0;
149 fs
->mountpoint
= path_parse(mountpoint
);
150 fs
->mountpoint_str
= path_output(fs
->mountpoint
,NULL
);
152 fs
->pid
= rpc_call("vfs_getpid",0,fs
->id
);
157 llist_push(fslist
,fs
);
164 * Gets list index by filehandle
165 * @param fh filehandle
168 static int lidxbyfh(int fh
) {
169 struct filelist_item
*file
;
171 for (i
=0;(file
= llist_get(filelist
,i
));i
++) {
172 if (file
->fh
==fh
) return i
;
178 * Gets absolute path by relative path
179 * @param relative Relative or absolute path
180 * @return Absolute path (Can be passed to free())
182 static char *getabsolutepath(const char *relative
) {
183 path_t
*path
= path_parse(relative
);
185 path_t
*newpath
= path_cat(workdir
.path
,path
);
189 path_reject_dots(path
);
190 return path_output(path
,NULL
);
194 * Creates an unnamed pipe
195 * @param read Whether creator is reader
198 int _create_unnamed_pipe(int read
,int *_shmid
) {
199 int shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
201 size_t *shmbuf
= shmat(shmid
,NULL
,0);
203 struct filelist_item
*new = malloc(sizeof(struct filelist_item
));
204 memset(new,0,sizeof(struct filelist_item
));
205 new->fh
= getnew_fh();
206 new->oflag
= read
?O_RDONLY
:O_WRONLY
;
208 new->shmbuf
= shmbuf
;
209 shmbuf
[0] = read
; // Direction
210 shmbuf
[1] = 0; // Reserved for error
211 shmbuf
[2] = 0; // Reading position
212 shmbuf
[3] = 0; // Writing position
213 llist_push(filelist
,new);
214 if (_shmid
!=NULL
) *_shmid
= shmid
;
217 else shmctl(shmid
,IPC_RMID
,NULL
);
223 * Destroys an unnamed pipe
224 * @param fh Filehandle of unnamed pipe
227 int _destroy_unnamed_pipe(int fh
) {
228 struct filelist_item
*file
= filebyfh(fh
);
230 if (file
&& file
->fs
==NULL
) {
232 shmctl(file
->shmid
,IPC_RMID
,NULL
);
233 llist_remove(filelist
,lidxbyfh(fh
));
242 * Opens an unnamed pipe
243 * @param fh Use this filehandle (-1 no specified filehandle)
244 * @param shmid SHM object the unnamed pipe uses
245 * @note If you specify the filehandle, be sure that it isn't used already
248 static int _open_unnamed_pipe(int fh
,int shmid
) {
249 size_t *shmbuf
= shmat(shmid
,NULL
,0);
251 if (fh
==-1) fh
= getnew_fh();
252 struct filelist_item
*new = malloc(sizeof(struct filelist_item
));
253 memset(new,0,sizeof(struct filelist_item
));
255 new->oflag
= shmbuf
[0]?O_WRONLY
:O_RDONLY
;
257 new->shmbuf
= shmbuf
;
258 llist_push(filelist
,new);
265 * Destroys an unnamed pipe
266 * @param fh Filehandle of unnamed pipe
269 static int _close_unnamed_pipe(int fh
) {
270 struct filelist_item
*file
= filebyfh(fh
);
272 if (file
&& file
->fs
==NULL
) {
274 llist_remove(filelist
,lidxbyfh(fh
));
283 * Reads an unnamed pipe
284 * @param fh Filehandle
285 * @param data Data buffer
286 * @param size How many bytes to read
287 * @return How many bytes read
289 static size_t _read_unnamed_pipe(int fh
,void *data
,size_t size
) {
290 struct filelist_item
*file
= filebyfh(fh
);
291 ssize_t size_read
= -1;
293 if (file
&& file
->fs
==NULL
&& file
->oflag
==O_RDONLY
) {
294 size_t *pos_read
= file
->shmbuf
+2*sizeof(size_t);
295 size_t *pos_write
= file
->shmbuf
+3*sizeof(size_t);
296 void *buffer
= file
->shmbuf
+4*sizeof(size_t);
297 size_t size_free
= *pos_write
>=*pos_read
?*pos_write
-*pos_read
:*pos_write
+SHMMEM_SIZE
-4*sizeof(int)-*pos_read
;
299 if (size
>size_free
) size
= size_free
;
300 if (*pos_write
>=*pos_read
) memcpy(data
,buffer
,size
);
302 size_t part1
= SHMMEM_SIZE
-4*sizeof(int)-*pos_read
;
303 size_t part2
= *pos_write
;
304 memcpy(data
,buffer
+*pos_read
,part1
);
305 memcpy(data
+part1
,buffer
,part2
);
307 *pos_read
= (*pos_read
+size
)%(SHMMEM_SIZE
-4*sizeof(int));
316 * Writes an unnamed pipe
317 * @param fh Filehandle
318 * @param data Data buffer
319 * @param size How many bytes to write
320 * @return How many bytes written
322 static size_t _write_unnamed_pipe(int fh
,const void *data
,size_t size
) {
323 struct filelist_item
*file
= filebyfh(fh
);
324 ssize_t size_written
= -1;
326 if (file
&& file
->fs
==NULL
&& file
->oflag
==O_WRONLY
) {
327 size_t *pos_read
= file
->shmbuf
+2*sizeof(size_t);
328 size_t *pos_write
= file
->shmbuf
+3*sizeof(size_t);
329 void *buffer
= file
->shmbuf
+4*sizeof(size_t);
330 size_t size_free
= *pos_read
>*pos_write
?*pos_read
-*pos_write
:*pos_read
+SHMMEM_SIZE
-4*sizeof(int)-*pos_write
;
332 if (size
>size_free
) size
= size_free
;
333 if (*pos_read
>=*pos_write
) memcpy(buffer
,data
,size
);
335 size_t part1
= SHMMEM_SIZE
-4*sizeof(int)-*pos_write
;
336 size_t part2
= *pos_read
;
337 memcpy(buffer
+*pos_write
,data
,part1
);
338 memcpy(buffer
,data
+part1
,part2
);
340 *pos_write
= (*pos_write
+size
)%(SHMMEM_SIZE
-4*sizeof(int));
349 * Gets current workdir
350 * @param buf Buffer to store path in
351 * @param size Size of buffer
352 * @return Current workdir
354 char *getcwd(char *buf
,size_t size
) {
356 size
= workdir
.strlen
+1;
363 else if (workdir
.strlen
+1>size
) {
367 return strncpy(buf
,workdir
.str
,size
);
371 * Change current workdir
372 * @param new New workdir
373 * @return 0=success; -1=failure
375 int chdir(const char *new) {
376 new = getabsolutepath((char*)new);
377 if (new==NULL
) new = "/";
379 /*DIR *dir = opendir(new);
383 path_destroy(workdir
.path
);
384 workdir
.path
= path_parse(new);
385 path_reject_dots(workdir
.path
);
386 workdir
.str
= path_output(workdir
.path
,NULL
);
387 workdir
.strlen
= strlen(workdir
.str
);
388 setenv("PATH",workdir
.str
,1);
395 * Change current workdir
396 * @param new Filedescriptor of new workdir
397 * @return 0=success; -1=failure
399 int fchdir(int fildes
) {
401 struct filelist_item
*file
= filebyfh(fildes
);
402 if (file
!=NULL
) res
= chdir(file
->path
);
404 errno
= res
<0?-res
:0;
410 * @param path Path to new node
411 * @param mode Mode of new node
412 * @param dev DeviceID (not used)
413 * @return 0=success; -1=failure
415 int mknod(const char *path
,mode_t mode
,dev_t dev
) {
417 char *cpath
= getabsolutepath((char*)path
);
418 struct fslist_item
*fs
= fsbypath(cpath
,1);
422 asprintf(&func
,"fs_mknod_%x",fs
->pid
);
423 res
= rpc_call(func
,0,fs
->id
,cpath
,mode
&(~creation_mask
),dev
);
428 errno
= res
<0?-res
:0;
433 * Checks whether file can be opened with mode
434 * @param path Path to file
436 * @return 0=success; -1=failure
438 int access(const char *path
,int amode
) {
440 char *cpath
= getabsolutepath((char*)path
);
441 struct fslist_item
*fs
= fsbypath(cpath
,0);
445 asprintf(&func
,"fs_access_%x",fs
->pid
);
446 res
= rpc_call(func
,0,fs
->id
,cpath
,amode
);
451 errno
= res
<0?-res
:0;
457 * @param path Path to file
460 int open(const char *path
,int oflag
,...) {
465 char *cpath
= getabsolutepath(path
);
466 struct fslist_item
*fs
= fsbypath(cpath
,0);
467 if (fs
==NULL
) fh
= -errno
;
469 va_start(args
,oflag
);
474 int res
= mknod(path
,va_arg(args
,mode_t
)|S_IFREG
,0);
475 if (res
==-1 && errno
!=EEXIST
) fh
= -errno
;
477 int shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
478 shmbuf
= shmat(shmid
,NULL
,0);
480 strncpy(shmbuf
,cpath
,SHMMEM_SIZE
);
481 asprintf(&func
,"fs_open_%x",fs
->pid
);
482 fh
= rpc_call(func
,0,fs
->id
,oflag
,shmid
);
485 struct filelist_item
*new = malloc(sizeof(struct filelist_item
));
490 new->fh
= getnew_fh();
491 new->path
= strdup(cpath
);
493 new->shmbuf
= shmbuf
;
495 llist_push(filelist
,new);
506 * Closes all filehandles
508 void _close_all_filehandles() {
509 struct filelist_item
*file
;
510 while ((file
= llist_pop(filelist
))!=NULL
) {
511 if (S_ISREG(file
->mode
)) close(file
->fh
);
512 else if (S_ISDIR(file
->mode
)) closedir(file
);
515 // close stdin, stdout and stderr
516 _destroy_unnamed_pipe(STDIN_FILENO
);
517 _destroy_unnamed_pipe(STDOUT_FILENO
);
518 _destroy_unnamed_pipe(STDERR_FILENO
);
524 * @param fildes File descriptor
525 * @return 0=success; -1=failure
527 int close(int fildes
) {
530 struct filelist_item
*file
= filebyfh(fildes
);
531 if (file
->fs
==NULL
) return _close_unnamed_pipe(fildes
);
533 asprintf(&func
,"fs_close_%x",file
->fs
->pid
);
534 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
);
538 shmctl(file
->shmid
,IPC_RMID
,NULL
);
539 llist_remove(filelist
,lidxbyfh(fildes
));
545 errno
= res
<0?-res
:0;
551 * Duplicates a file descriptor
552 * @param fildes File descriptor
553 * @param fildes2 New file descriptor
554 * @return New file desciptor
556 int dup2(int fildes
,int fildes2
) {
559 struct filelist_item
*file
= filebyfh(fildes
);
561 asprintf(&func
,"fs_close_%x",file
->fs
->pid
);
562 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
);
565 struct filelist_item
*new = malloc(sizeof(struct filelist_item
));
566 memcpy(new,file
,sizeof(struct filelist_item
));
567 if (fildes2
==0) new->fh
= getnew_fh();
573 new->shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
574 new->shmbuf
= shmat(new->shmid
,NULL
,0);
575 llist_push(filelist
,new);
584 * @param fildes File descriptor
585 * @param buf Buffer to store read data in
586 * @param count How many bytes to read
587 * @return How many bytes read
589 static ssize_t
_read(struct filelist_item
*file
,void *buf
,size_t count
) {
592 asprintf(&func
,"fs_read_%x",file
->fs
->pid
);
593 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
,count
);
595 if (res
>0) memcpy(buf
,file
->shmbuf
,res
);
598 ssize_t
read(int fildes
,void *buf
,size_t count
) {
599 struct filelist_item
*file
= filebyfh(fildes
);
600 if (file
->fs
==NULL
) return _read_unnamed_pipe(fildes
,buf
,count
);
601 else if (file
!=NULL
) {
602 ssize_t count_rem
= count
;
605 while (count_rem
>0) {
606 size_t count_cur
= count_rem
;
607 if (count_cur
>SHMMEM_SIZE
) count_cur
= SHMMEM_SIZE
;
608 count_cur
= _read(file
,buf
+off
,count_cur
);
609 if (count_cur
==-1) return -1;
610 count_rem
-= count_cur
;
611 if (count_cur
==0) break;
615 return count
-count_rem
;
625 * @param fildes File descriptor
626 * @param buf Data to write to file
627 * @param count How many bytes to write
628 * @return How many bytes written
630 static ssize_t
_write(struct filelist_item
*file
,const void *buf
,size_t count
) {
633 memcpy(file
->shmbuf
,buf
,count
);
634 asprintf(&func
,"fs_write_%x",file
->fs
->pid
);
635 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
,count
);
639 ssize_t
write(int fildes
,const void *buf
,size_t count
) {
640 struct filelist_item
*file
= filebyfh(fildes
);
641 if (file
->fs
==NULL
) return _write_unnamed_pipe(fildes
,buf
,count
);
643 ssize_t count_rem
= count
;
645 while (count_rem
>0) {
646 size_t count_cur
= count_rem
;
647 if (count_cur
>SHMMEM_SIZE
) count_cur
= SHMMEM_SIZE
;
648 count_cur
= _write(file
,buf
+off
,count_cur
);
649 if (count_cur
==-1) return -1;
650 count_rem
-= count_cur
;
651 if (count_cur
==0) break;
654 return count
-count_rem
;
664 * @param fildes File descriptor
665 * @param offset Offset
666 * @param whence SEEK_SET, SEEK_CUR, SEEK_END
667 * @return New position
669 off_t
lseek(int fildes
,off_t offset
,int whence
) {
672 struct filelist_item
*file
= filebyfh(fildes
);
674 asprintf(&func
,"fs_seek_%x",file
->fs
->pid
);
675 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
,offset
,whence
);
679 errno
= res
<0?-res
:0;
685 * @param path Path to file
686 * @return 0=success; -1=failure
688 int unlink(const char *path
) {
690 char *cpath
= getabsolutepath((char*)path
);
691 struct fslist_item
*fs
= fsbypath(cpath
,1);
695 asprintf(&func
,"fs_unlink_%x",fs
->pid
);
696 res
= rpc_call(func
,0,fs
->id
,cpath
);
701 errno
= res
<0?-res
:0;
706 * Removes a directory
707 * @param path Path to directory
708 * @return 0=success; -1=failure
710 int rmdir(const char *path
) {
712 char *cpath
= getabsolutepath((char*)path
);
713 struct fslist_item
*fs
= fsbypath(cpath
,1);
717 asprintf(&func
,"fs_rmdir_%x",fs
->pid
);
718 res
= rpc_call(func
,0,fs
->id
,cpath
);
723 errno
= res
<0?-res
:0;
729 * @param path Path to directory
730 * @return 0=success; -1=failure
732 int rename(const char *old
, const char *new) {
734 char *cold
= getabsolutepath((char*)old
);
735 char *cnew
= getabsolutepath((char*)new);
736 struct fslist_item
*fs
= fsbypath(cold
,1);
737 struct fslist_item
*fsnew
= fsbypath(cnew
,1);
740 if (fs
!=NULL
&& fs
==fsnew
) {
741 asprintf(&func
,"fs_rename_%x",fs
->pid
);
742 res
= rpc_call(func
,0,fs
->id
,old
,new);
746 errno
= res
<0?-res
:0;
753 * @param length New length
754 * @return 0=success; -1=failure
756 int truncate(const char *path
,off_t length
) {
759 if ((fh
= open(path
,O_WRONLY
))!=-1) {
760 if (ftruncate(fh
,length
)!=-1) res
= 0;
768 * @param fildes File descriptor
769 * @param length New length
770 * @return 0=success; -1=failure
772 int ftruncate(int fildes
,off_t length
) {
775 struct filelist_item
*file
= filebyfh(fildes
);
777 asprintf(&func
,"fs_ftruncate_%x",file
->fs
->pid
);
778 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
,length
);
782 errno
= res
<0?-res
:0;
789 * @param path Path to directory
790 * @return Pointer to dir handle
792 DIR *opendir(const char *path
) {
796 char *cpath
= getabsolutepath(path
);
797 struct fslist_item
*fs
= fsbypath(cpath
,0);
799 struct filelist_item
*new;
801 int shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
802 shmbuf
= shmat(shmid
,NULL
,0);
804 strncpy(shmbuf
,cpath
,SHMMEM_SIZE
);
805 asprintf(&func
,"fs_opendir_%x",fs
->pid
);
806 dh
= rpc_call(func
,0,fs
->id
,shmid
);
809 new = malloc(sizeof(struct filelist_item
));
814 new->fh
= 0; // Dir handles don't need IDs
815 new->path
= strdup(cpath
);
817 new->shmbuf
= shmbuf
;
818 new->dir_cur
.d_name
= NULL
;
819 llist_push(filelist
,new);
828 errno
= res
<0?-res
:0;
829 return res
<0?NULL
:((DIR*)new);
834 * @param file Dirhandle
837 int closedir(DIR *file
) {
841 asprintf(&func
,"fs_closedir_%x",file
->fs
->pid
);
842 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
);
846 shmctl(file
->shmid
,IPC_RMID
,NULL
);
849 llist_remove(filelist
,llist_find(filelist
,file
));
853 errno
= res
<0?-res
:0;
858 * Reads an entry from an opened dir
859 * @param dh Dirhandle
862 struct dirent
*readdir(DIR *file
) {
866 asprintf(&func
,"fs_readdir_%x",file
->fs
->pid
);
867 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
);
870 if (file
->dir_cur
.d_name
!=NULL
) free(file
->dir_cur
.d_name
);
871 file
->dir_cur
.d_name
= strdup(file
->shmbuf
);
875 errno
= res
<0 && res
!=-ENOENT
?-res
:0;
876 return res
<0?NULL
:&(file
->dir_cur
);
881 * @param dh Dirhandle
882 * @param loc Location to seek to
884 void seekdir(DIR *file
,long loc
) {
888 asprintf(&func
,"fs_seekdir_%x",file
->fs
->pid
);
889 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
,loc
);
893 errno
= res
<0?-res
:0;
897 * Gets location in dir
898 * @param dh Dirhandle
899 * @return Location in dir
901 long telldir(DIR *file
) {
905 asprintf(&func
,"fs_seekdir_%x",file
->fs
->pid
);
906 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
,-1);
910 errno
= res
<0?-res
:0;
915 * Gets informations about a file
916 * @param path Path to file
917 * @param buf Pointer to stat structure
918 * @return 0=success; -1=failure
920 int stat(const char *path
,struct stat
*buf
) {
923 if ((fh
= open(path
,O_RDONLY
))!=-1) {
928 struct filelist_item
*dir
= opendir(path
);
930 ret
= fstat(dir
->fh
,buf
);
938 * Gets informations about a filedescriptor
939 * @param fildes Filedescriptor
940 * @param buf Pointer to stat structure
941 * @return 0=success; -1=failure
943 int fstat(int fildes
,struct stat
*buf
) {
946 struct filelist_item
*file
= filebyfh(fildes
);
948 asprintf(&func
,"fs_fstat_%x",file
->fs
->pid
);
949 memset(buf
,0,sizeof(struct stat
));
950 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
);
951 memcpy(buf
,file
->shmbuf
,sizeof(struct stat
));
955 errno
= res
<0?-res
:0;
960 * Gets informations about a filesystem
961 * @param path File included in FS of that information is wanted
962 * @param buf Pointer to statvfs structure
965 int statvfs(const char *path
,struct statvfs
*buf
) {
969 char *cpath
= getabsolutepath(path
);
970 struct fslist_item
*fs
= fsbypath(cpath
,0);
973 int shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
974 shmbuf
= shmat(shmid
,NULL
,0);
976 asprintf(&func
,"fs_statvfs_%x",fs
->pid
);
977 memset(buf
,0,sizeof(struct statvfs
));
978 strncpy(shmbuf
,cpath
,SHMMEM_SIZE
);
979 res
= rpc_call(func
,0,fs
->id
,shmid
);
980 memcpy(buf
,shmbuf
,sizeof(struct statvfs
));
983 shmctl(shmid
,IPC_RMID
,NULL
);
989 errno
= res
<0?-res
:0;
995 * @param path Path to link
996 * @param buf Buffer for path
997 * @param bufsize Size of buffer
998 * @return Bytes written to buffer
1000 ssize_t
readlink(const char *path
,char *buf
,size_t bufsize
) {
1004 char *cpath
= getabsolutepath(path
);
1005 struct fslist_item
*fs
= fsbypath(cpath
,0);
1008 int shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
1009 shmbuf
= shmat(shmid
,NULL
,0);
1011 asprintf(&func
,"fs_readlink_%x",fs
->pid
);
1012 strncpy(shmbuf
,cpath
,SHMMEM_SIZE
);
1013 res
= rpc_call(func
,0,fs
->id
,shmid
,bufsize
);
1014 strncpy(buf
,shmbuf
,bufsize
);
1017 shmctl(shmid
,IPC_RMID
,NULL
);
1023 errno
= res
<0?-res
:0;
1024 return res
<0?-1:res
;
1028 * Creates a symoblic link
1029 * @param src Source file
1030 * @param dest Destination (name of symlink)
1031 * @return 0=success; -1=failure
1033 int symlink(const char *dest
,const char *src
) {
1035 char *csrc
= getabsolutepath((char*)src
);
1036 char *cdest
= getabsolutepath((char*)dest
);
1037 struct fslist_item
*fs
= fsbypath(csrc
,1);
1041 asprintf(&func
,"fs_symlink_%x",fs
->pid
);
1042 res
= rpc_call(func
,0,fs
->id
,csrc
,cdest
);
1046 errno
= res
<0?-res
:0;
1047 return res
<0?-1:res
;
1051 * Creates a hardlink
1052 * @param src Source file
1053 * @param dest Destination (name of hardlink)
1054 * @return 0=success; -1=failure
1056 int link(const char *src
,const char *dest
) {
1058 char *csrc
= getabsolutepath((char*)src
);
1059 char *cdest
= getabsolutepath((char*)dest
);
1060 struct fslist_item
*fs
= fsbypath(csrc
,1);
1061 struct fslist_item
*fsdest
= fsbypath(cdest
,0);
1064 if (fs
!=NULL
&& fs
==fsdest
) {
1065 asprintf(&func
,"fs_link_%x",fs
->pid
);
1066 res
= rpc_call(func
,0,fs
->id
,src
,dest
);
1070 errno
= res
<0?-res
:0;
1071 return res
<0?-1:res
;
1074 int chown(const char *path
,uid_t uid
,gid_t gid
) {
1076 char *cpath
= getabsolutepath((char*)path
);
1077 struct fslist_item
*fs
= fsbypath(cpath
,0);
1081 asprintf(&func
,"fs_chown_%x",fs
->pid
);
1082 res
= rpc_call(func
,0,fs
->id
,cpath
,uid
,gid
);
1087 errno
= res
<0?-res
:0;
1088 return res
<0?-1:res
;
1091 int fchown(int fildes
,uid_t uid
,gid_t gid
) {
1093 struct filelist_item
*file
= filebyfh(fildes
);
1094 if (file
) res
= chown(file
->path
,uid
,gid
);
1096 errno
= res
<0?-res
:0;
1097 return res
<0?-1:res
;
1100 int chmod(const char *path
,mode_t mode
) {
1102 char *cpath
= getabsolutepath((char*)path
);
1103 struct fslist_item
*fs
= fsbypath(cpath
,0);
1107 asprintf(&func
,"fs_chmod_%x",fs
->pid
);
1108 res
= rpc_call(func
,0,fs
->id
,cpath
,mode
);
1113 errno
= res
<0?-res
:0;
1114 return res
<0?-1:res
;
1117 int fchmod(int fildes
,mode_t mode
) {
1119 struct filelist_item
*file
= filebyfh(fildes
);
1121 res
= chmod(file
->path
,mode
);
1122 if (res
==0) file
->mode
= mode
;
1125 errno
= res
<0?-res
:0;
1126 return res
<0?-1:res
;
1129 int utime(const char *path
,const struct utimbuf
*times
) {
1133 char *cpath
= getabsolutepath(path
);
1134 struct fslist_item
*fs
= fsbypath(cpath
,0);
1137 int shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
1138 shmbuf
= shmat(shmid
,NULL
,0);
1140 asprintf(&func
,"fs_utime_%x",fs
->pid
);
1141 strncpy(shmbuf
,path
,SHMMEM_SIZE
);
1142 memcpy(shmbuf
+strlen(shmbuf
)+1,times
,sizeof(struct utimbuf
));
1143 res
= rpc_call(func
,0,fs
->id
,shmid
);
1146 shmctl(shmid
,IPC_RMID
,NULL
);
1152 errno
= res
<0?-res
:0;
1153 return res
<0?-1:res
;
1156 mode_t
umask(mode_t cmask
) {
1157 mode_t ret
= creation_mask
;
1158 creation_mask
= cmask
&0777;
1162 ///////// SOCKET STUFF /////////////////////
1164 int socket(int domain
,int type
, int protocol
) {