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 if (path
==NULL
|| path
[0]==0) return NULL
;
139 struct fslist_item
*fs
= mp_match(path
,parent
);
141 fs
= malloc(sizeof(struct fslist_item
));
142 char *mountpoint
= strdup(path
);
143 fs
->id
= rpc_call("vfs_getfsid",2,path
,parent
);
149 mountpoint
[strlen(mountpoint
)-strlen(path
)] = 0;
150 fs
->mountpoint
= path_parse(mountpoint
);
151 fs
->mountpoint_str
= path_output(fs
->mountpoint
,NULL
);
153 fs
->pid
= rpc_call("vfs_getpid",0,fs
->id
);
158 llist_push(fslist
,fs
);
165 * Gets list index by filehandle
166 * @param fh filehandle
169 static int lidxbyfh(int fh
) {
170 struct filelist_item
*file
;
172 for (i
=0;(file
= llist_get(filelist
,i
));i
++) {
173 if (file
->fh
==fh
) return i
;
179 * Gets absolute path by relative path
180 * @param relative Relative or absolute path
181 * @return Absolute path (Can be passed to free())
183 static char *getabsolutepath(const char *relative
) {
184 path_t
*path
= path_parse(relative
);
186 path_t
*newpath
= path_cat(workdir
.path
,path
);
190 path_reject_dots(path
);
191 return path_output(path
,NULL
);
195 * Creates an unnamed pipe
196 * @param read Whether creator is reader
199 int _create_unnamed_pipe(int read
,int *_shmid
) {
200 int shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
202 size_t *shmbuf
= shmat(shmid
,NULL
,0);
204 struct filelist_item
*new = malloc(sizeof(struct filelist_item
));
205 memset(new,0,sizeof(struct filelist_item
));
206 new->fh
= getnew_fh();
207 new->oflag
= read
?O_RDONLY
:O_WRONLY
;
209 new->shmbuf
= shmbuf
;
210 shmbuf
[0] = read
; // Direction
211 shmbuf
[1] = 0; // Reserved for error
212 shmbuf
[2] = 0; // Reading position
213 shmbuf
[3] = 0; // Writing position
214 llist_push(filelist
,new);
215 if (_shmid
!=NULL
) *_shmid
= shmid
;
218 else shmctl(shmid
,IPC_RMID
,NULL
);
224 * Destroys an unnamed pipe
225 * @param fh Filehandle of unnamed pipe
228 int _destroy_unnamed_pipe(int fh
) {
229 struct filelist_item
*file
= filebyfh(fh
);
231 if (file
&& file
->fs
==NULL
) {
233 shmctl(file
->shmid
,IPC_RMID
,NULL
);
234 llist_remove(filelist
,lidxbyfh(fh
));
243 * Opens an unnamed pipe
244 * @param fh Use this filehandle (-1 no specified filehandle)
245 * @param shmid SHM object the unnamed pipe uses
246 * @note If you specify the filehandle, be sure that it isn't used already
249 static int _open_unnamed_pipe(int fh
,int shmid
) {
250 size_t *shmbuf
= shmat(shmid
,NULL
,0);
252 if (fh
==-1) fh
= getnew_fh();
253 struct filelist_item
*new = malloc(sizeof(struct filelist_item
));
254 memset(new,0,sizeof(struct filelist_item
));
256 new->oflag
= shmbuf
[0]?O_WRONLY
:O_RDONLY
;
258 new->shmbuf
= shmbuf
;
259 llist_push(filelist
,new);
266 * Destroys an unnamed pipe
267 * @param fh Filehandle of unnamed pipe
270 static int _close_unnamed_pipe(int fh
) {
271 struct filelist_item
*file
= filebyfh(fh
);
273 if (file
&& file
->fs
==NULL
) {
275 llist_remove(filelist
,lidxbyfh(fh
));
284 * Reads an unnamed pipe
285 * @param fh Filehandle
286 * @param data Data buffer
287 * @param size How many bytes to read
288 * @return How many bytes read
290 static size_t _read_unnamed_pipe(int fh
,void *data
,size_t size
) {
291 struct filelist_item
*file
= filebyfh(fh
);
292 ssize_t size_read
= -1;
294 if (file
&& file
->fs
==NULL
&& file
->oflag
==O_RDONLY
) {
295 size_t *pos_read
= file
->shmbuf
+2*sizeof(size_t);
296 size_t *pos_write
= file
->shmbuf
+3*sizeof(size_t);
297 void *buffer
= file
->shmbuf
+4*sizeof(size_t);
298 size_t size_free
= *pos_write
>=*pos_read
?*pos_write
-*pos_read
:*pos_write
+SHMMEM_SIZE
-4*sizeof(int)-*pos_read
;
300 if (size
>size_free
) size
= size_free
;
301 if (*pos_write
>=*pos_read
) memcpy(data
,buffer
,size
);
303 size_t part1
= SHMMEM_SIZE
-4*sizeof(int)-*pos_read
;
304 size_t part2
= *pos_write
;
305 memcpy(data
,buffer
+*pos_read
,part1
);
306 memcpy(data
+part1
,buffer
,part2
);
308 *pos_read
= (*pos_read
+size
)%(SHMMEM_SIZE
-4*sizeof(int));
317 * Writes an unnamed pipe
318 * @param fh Filehandle
319 * @param data Data buffer
320 * @param size How many bytes to write
321 * @return How many bytes written
323 static size_t _write_unnamed_pipe(int fh
,const void *data
,size_t size
) {
324 struct filelist_item
*file
= filebyfh(fh
);
325 ssize_t size_written
= -1;
327 if (file
&& file
->fs
==NULL
&& file
->oflag
==O_WRONLY
) {
328 size_t *pos_read
= file
->shmbuf
+2*sizeof(size_t);
329 size_t *pos_write
= file
->shmbuf
+3*sizeof(size_t);
330 void *buffer
= file
->shmbuf
+4*sizeof(size_t);
331 size_t size_free
= *pos_read
>*pos_write
?*pos_read
-*pos_write
:*pos_read
+SHMMEM_SIZE
-4*sizeof(int)-*pos_write
;
333 if (size
>size_free
) size
= size_free
;
334 if (*pos_read
>=*pos_write
) memcpy(buffer
,data
,size
);
336 size_t part1
= SHMMEM_SIZE
-4*sizeof(int)-*pos_write
;
337 size_t part2
= *pos_read
;
338 memcpy(buffer
+*pos_write
,data
,part1
);
339 memcpy(buffer
,data
+part1
,part2
);
341 *pos_write
= (*pos_write
+size
)%(SHMMEM_SIZE
-4*sizeof(int));
350 * Gets current workdir
351 * @param buf Buffer to store path in
352 * @param size Size of buffer
353 * @return Current workdir
355 char *getcwd(char *buf
,size_t size
) {
357 size
= workdir
.strlen
+1;
364 else if (workdir
.strlen
+1>size
) {
368 return strncpy(buf
,workdir
.str
,size
);
372 * Change current workdir
373 * @param new New workdir
374 * @return 0=success; -1=failure
376 int chdir(const char *new) {
377 new = getabsolutepath((char*)new);
378 if (new==NULL
) new = "/";
380 DIR *dir
= opendir(new);
384 path_destroy(workdir
.path
);
385 workdir
.path
= path_parse(new);
386 path_reject_dots(workdir
.path
);
387 workdir
.str
= path_output(workdir
.path
,NULL
);
388 workdir
.strlen
= strlen(workdir
.str
);
389 setenv("PATH",workdir
.str
,1);
396 * Change current workdir
397 * @param new Filedescriptor of new workdir
398 * @return 0=success; -1=failure
400 int fchdir(int fildes
) {
402 struct filelist_item
*file
= filebyfh(fildes
);
403 if (file
!=NULL
) res
= chdir(file
->path
);
405 errno
= res
<0?-res
:0;
411 * @param path Path to new node
412 * @param mode Mode of new node
413 * @param dev DeviceID (not used)
414 * @return 0=success; -1=failure
416 int mknod(const char *path
,mode_t mode
,dev_t dev
) {
418 char *cpath
= getabsolutepath((char*)path
);
419 struct fslist_item
*fs
= fsbypath(cpath
,1);
423 asprintf(&func
,"fs_mknod_%x",fs
->pid
);
424 res
= rpc_call(func
,0,fs
->id
,cpath
,mode
&(~creation_mask
),dev
);
429 errno
= res
<0?-res
:0;
434 * Checks whether file can be opened with mode
435 * @param path Path to file
437 * @return 0=success; -1=failure
439 int access(const char *path
,int amode
) {
441 char *cpath
= getabsolutepath((char*)path
);
442 struct fslist_item
*fs
= fsbypath(cpath
,0);
446 asprintf(&func
,"fs_access_%x",fs
->pid
);
447 res
= rpc_call(func
,0,fs
->id
,cpath
,amode
);
452 errno
= res
<0?-res
:0;
458 * @param path Path to file
461 int open(const char *path
,int oflag
,...) {
466 char *cpath
= getabsolutepath(path
);
467 struct fslist_item
*fs
= fsbypath(cpath
,0);
468 if (fs
==NULL
) fh
= -errno
;
470 va_start(args
,oflag
);
475 int res
= mknod(path
,va_arg(args
,mode_t
)|S_IFREG
,0);
476 if (res
==-1 && errno
!=EEXIST
) fh
= -errno
;
478 int shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
479 shmbuf
= shmat(shmid
,NULL
,0);
481 strncpy(shmbuf
,cpath
,SHMMEM_SIZE
);
482 asprintf(&func
,"fs_open_%x",fs
->pid
);
483 fh
= rpc_call(func
,0,fs
->id
,oflag
,shmid
);
486 struct filelist_item
*new = malloc(sizeof(struct filelist_item
));
491 new->fh
= getnew_fh();
492 new->path
= strdup(cpath
);
494 new->shmbuf
= shmbuf
;
496 llist_push(filelist
,new);
507 * Closes all filehandles
509 void _close_all_filehandles() {
510 struct filelist_item
*file
;
511 while ((file
= llist_pop(filelist
))!=NULL
) {
512 if (S_ISREG(file
->mode
)) close(file
->fh
);
513 else if (S_ISDIR(file
->mode
)) closedir(file
);
516 // close stdin, stdout and stderr
517 _destroy_unnamed_pipe(STDIN_FILENO
);
518 _destroy_unnamed_pipe(STDOUT_FILENO
);
519 _destroy_unnamed_pipe(STDERR_FILENO
);
525 * @param fildes File descriptor
526 * @return 0=success; -1=failure
528 int close(int fildes
) {
531 struct filelist_item
*file
= filebyfh(fildes
);
532 if (file
->fs
==NULL
) return _close_unnamed_pipe(fildes
);
534 asprintf(&func
,"fs_close_%x",file
->fs
->pid
);
535 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
);
539 shmctl(file
->shmid
,IPC_RMID
,NULL
);
540 llist_remove(filelist
,lidxbyfh(fildes
));
546 errno
= res
<0?-res
:0;
552 * Duplicates a file descriptor
553 * @param fildes File descriptor
554 * @param fildes2 New file descriptor
555 * @return New file desciptor
557 int dup2(int fildes
,int fildes2
) {
560 struct filelist_item
*file
= filebyfh(fildes
);
562 asprintf(&func
,"fs_close_%x",file
->fs
->pid
);
563 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
);
566 struct filelist_item
*new = malloc(sizeof(struct filelist_item
));
567 memcpy(new,file
,sizeof(struct filelist_item
));
568 if (fildes2
==0) new->fh
= getnew_fh();
574 new->shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
575 new->shmbuf
= shmat(new->shmid
,NULL
,0);
576 llist_push(filelist
,new);
585 * @param fildes File descriptor
586 * @param buf Buffer to store read data in
587 * @param count How many bytes to read
588 * @return How many bytes read
590 static ssize_t
_read(struct filelist_item
*file
,void *buf
,size_t count
) {
593 asprintf(&func
,"fs_read_%x",file
->fs
->pid
);
594 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
,count
);
596 if (res
>0) memcpy(buf
,file
->shmbuf
,res
);
599 ssize_t
read(int fildes
,void *buf
,size_t count
) {
600 struct filelist_item
*file
= filebyfh(fildes
);
601 if (file
->fs
==NULL
) return _read_unnamed_pipe(fildes
,buf
,count
);
602 else if (file
!=NULL
) {
603 ssize_t count_rem
= count
;
606 while (count_rem
>0) {
607 size_t count_cur
= count_rem
;
608 if (count_cur
>SHMMEM_SIZE
) count_cur
= SHMMEM_SIZE
;
609 count_cur
= _read(file
,buf
+off
,count_cur
);
610 if (count_cur
==-1) return -1;
611 count_rem
-= count_cur
;
612 if (count_cur
==0) break;
616 return count
-count_rem
;
626 * @param fildes File descriptor
627 * @param buf Data to write to file
628 * @param count How many bytes to write
629 * @return How many bytes written
631 static ssize_t
_write(struct filelist_item
*file
,const void *buf
,size_t count
) {
634 memcpy(file
->shmbuf
,buf
,count
);
635 asprintf(&func
,"fs_write_%x",file
->fs
->pid
);
636 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
,count
);
640 ssize_t
write(int fildes
,const void *buf
,size_t count
) {
641 struct filelist_item
*file
= filebyfh(fildes
);
642 if (file
->fs
==NULL
) return _write_unnamed_pipe(fildes
,buf
,count
);
644 ssize_t count_rem
= count
;
646 while (count_rem
>0) {
647 size_t count_cur
= count_rem
;
648 if (count_cur
>SHMMEM_SIZE
) count_cur
= SHMMEM_SIZE
;
649 count_cur
= _write(file
,buf
+off
,count_cur
);
650 if (count_cur
==-1) return -1;
651 count_rem
-= count_cur
;
652 if (count_cur
==0) break;
655 return count
-count_rem
;
665 * @param fildes File descriptor
666 * @param offset Offset
667 * @param whence SEEK_SET, SEEK_CUR, SEEK_END
668 * @return New position
670 off_t
lseek(int fildes
,off_t offset
,int whence
) {
673 struct filelist_item
*file
= filebyfh(fildes
);
675 asprintf(&func
,"fs_seek_%x",file
->fs
->pid
);
676 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
,offset
,whence
);
680 errno
= res
<0?-res
:0;
686 * @param path Path to file
687 * @return 0=success; -1=failure
689 int unlink(const char *path
) {
691 char *cpath
= getabsolutepath((char*)path
);
692 struct fslist_item
*fs
= fsbypath(cpath
,1);
696 asprintf(&func
,"fs_unlink_%x",fs
->pid
);
697 res
= rpc_call(func
,0,fs
->id
,cpath
);
702 errno
= res
<0?-res
:0;
707 * Removes a directory
708 * @param path Path to directory
709 * @return 0=success; -1=failure
711 int rmdir(const char *path
) {
713 char *cpath
= getabsolutepath((char*)path
);
714 struct fslist_item
*fs
= fsbypath(cpath
,1);
718 asprintf(&func
,"fs_rmdir_%x",fs
->pid
);
719 res
= rpc_call(func
,0,fs
->id
,cpath
);
724 errno
= res
<0?-res
:0;
730 * @param path Path to directory
731 * @return 0=success; -1=failure
733 int rename(const char *old
, const char *new) {
735 char *cold
= getabsolutepath((char*)old
);
736 char *cnew
= getabsolutepath((char*)new);
737 struct fslist_item
*fs
= fsbypath(cold
,1);
738 struct fslist_item
*fsnew
= fsbypath(cnew
,1);
741 if (fs
!=NULL
&& fs
==fsnew
) {
742 asprintf(&func
,"fs_rename_%x",fs
->pid
);
743 res
= rpc_call(func
,0,fs
->id
,old
,new);
747 errno
= res
<0?-res
:0;
754 * @param length New length
755 * @return 0=success; -1=failure
757 int truncate(const char *path
,off_t length
) {
760 if ((fh
= open(path
,O_WRONLY
))!=-1) {
761 if (ftruncate(fh
,length
)!=-1) res
= 0;
769 * @param fildes File descriptor
770 * @param length New length
771 * @return 0=success; -1=failure
773 int ftruncate(int fildes
,off_t length
) {
776 struct filelist_item
*file
= filebyfh(fildes
);
778 asprintf(&func
,"fs_ftruncate_%x",file
->fs
->pid
);
779 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
,length
);
783 errno
= res
<0?-res
:0;
790 * @param path Path to directory
791 * @return Pointer to dir handle
793 DIR *opendir(const char *path
) {
797 char *cpath
= getabsolutepath(path
);
798 struct fslist_item
*fs
= fsbypath(cpath
,0);
800 struct filelist_item
*new;
802 int shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
803 shmbuf
= shmat(shmid
,NULL
,0);
805 strncpy(shmbuf
,cpath
,SHMMEM_SIZE
);
806 asprintf(&func
,"fs_opendir_%x",fs
->pid
);
807 dh
= rpc_call(func
,0,fs
->id
,shmid
);
810 new = malloc(sizeof(struct filelist_item
));
815 new->fh
= 0; // Dir handles don't need IDs
816 new->path
= strdup(cpath
);
818 new->shmbuf
= shmbuf
;
819 new->dir_cur
.d_name
= NULL
;
820 llist_push(filelist
,new);
829 errno
= res
<0?-res
:0;
830 return res
<0?NULL
:((DIR*)new);
835 * @param file Dirhandle
838 int closedir(DIR *file
) {
842 asprintf(&func
,"fs_closedir_%x",file
->fs
->pid
);
843 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
);
847 shmctl(file
->shmid
,IPC_RMID
,NULL
);
850 llist_remove(filelist
,llist_find(filelist
,file
));
854 errno
= res
<0?-res
:0;
859 * Reads an entry from an opened dir
860 * @param dh Dirhandle
863 struct dirent
*readdir(DIR *file
) {
867 asprintf(&func
,"fs_readdir_%x",file
->fs
->pid
);
868 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
);
871 if (file
->dir_cur
.d_name
!=NULL
) free(file
->dir_cur
.d_name
);
872 file
->dir_cur
.d_name
= strdup(file
->shmbuf
);
876 errno
= res
<0 && res
!=-ENOENT
?-res
:0;
877 return res
<0?NULL
:&(file
->dir_cur
);
882 * @param dh Dirhandle
883 * @param loc Location to seek to
885 void seekdir(DIR *file
,long loc
) {
889 asprintf(&func
,"fs_seekdir_%x",file
->fs
->pid
);
890 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
,loc
);
894 errno
= res
<0?-res
:0;
898 * Gets location in dir
899 * @param dh Dirhandle
900 * @return Location in dir
902 long telldir(DIR *file
) {
906 asprintf(&func
,"fs_seekdir_%x",file
->fs
->pid
);
907 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
,-1);
911 errno
= res
<0?-res
:0;
916 * Gets informations about a file
917 * @param path Path to file
918 * @param buf Pointer to stat structure
919 * @return 0=success; -1=failure
921 int stat(const char *path
,struct stat
*buf
) {
924 if ((fh
= open(path
,O_RDONLY
))!=-1) {
929 struct filelist_item
*dir
= opendir(path
);
931 ret
= fstat(dir
->fh
,buf
);
939 * Gets informations about a filedescriptor
940 * @param fildes Filedescriptor
941 * @param buf Pointer to stat structure
942 * @return 0=success; -1=failure
944 int fstat(int fildes
,struct stat
*buf
) {
947 struct filelist_item
*file
= filebyfh(fildes
);
949 asprintf(&func
,"fs_fstat_%x",file
->fs
->pid
);
950 memset(buf
,0,sizeof(struct stat
));
951 res
= rpc_call(func
,0,file
->fs
->id
,file
->fs_fh
);
952 memcpy(buf
,file
->shmbuf
,sizeof(struct stat
));
956 errno
= res
<0?-res
:0;
961 * Gets informations about a filesystem
962 * @param path File included in FS of that information is wanted
963 * @param buf Pointer to statvfs structure
966 int statvfs(const char *path
,struct statvfs
*buf
) {
970 char *cpath
= getabsolutepath(path
);
971 struct fslist_item
*fs
= fsbypath(cpath
,0);
974 int shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
975 shmbuf
= shmat(shmid
,NULL
,0);
977 asprintf(&func
,"fs_statvfs_%x",fs
->pid
);
978 memset(buf
,0,sizeof(struct statvfs
));
979 strncpy(shmbuf
,cpath
,SHMMEM_SIZE
);
980 res
= rpc_call(func
,0,fs
->id
,shmid
);
981 memcpy(buf
,shmbuf
,sizeof(struct statvfs
));
984 shmctl(shmid
,IPC_RMID
,NULL
);
990 errno
= res
<0?-res
:0;
996 * @param path Path to link
997 * @param buf Buffer for path
998 * @param bufsize Size of buffer
999 * @return Bytes written to buffer
1001 ssize_t
readlink(const char *path
,char *buf
,size_t bufsize
) {
1005 char *cpath
= getabsolutepath(path
);
1006 struct fslist_item
*fs
= fsbypath(cpath
,0);
1009 int shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
1010 shmbuf
= shmat(shmid
,NULL
,0);
1012 asprintf(&func
,"fs_readlink_%x",fs
->pid
);
1013 strncpy(shmbuf
,cpath
,SHMMEM_SIZE
);
1014 res
= rpc_call(func
,0,fs
->id
,shmid
,bufsize
);
1015 strncpy(buf
,shmbuf
,bufsize
);
1018 shmctl(shmid
,IPC_RMID
,NULL
);
1024 errno
= res
<0?-res
:0;
1025 return res
<0?-1:res
;
1029 * Creates a symoblic link
1030 * @param src Source file
1031 * @param dest Destination (name of symlink)
1032 * @return 0=success; -1=failure
1034 int symlink(const char *dest
,const char *src
) {
1036 char *csrc
= getabsolutepath((char*)src
);
1037 char *cdest
= getabsolutepath((char*)dest
);
1038 struct fslist_item
*fs
= fsbypath(csrc
,1);
1042 asprintf(&func
,"fs_symlink_%x",fs
->pid
);
1043 res
= rpc_call(func
,0,fs
->id
,csrc
,cdest
);
1047 errno
= res
<0?-res
:0;
1048 return res
<0?-1:res
;
1052 * Creates a hardlink
1053 * @param src Source file
1054 * @param dest Destination (name of hardlink)
1055 * @return 0=success; -1=failure
1057 int link(const char *src
,const char *dest
) {
1059 char *csrc
= getabsolutepath((char*)src
);
1060 char *cdest
= getabsolutepath((char*)dest
);
1061 struct fslist_item
*fs
= fsbypath(csrc
,1);
1062 struct fslist_item
*fsdest
= fsbypath(cdest
,0);
1065 if (fs
!=NULL
&& fs
==fsdest
) {
1066 asprintf(&func
,"fs_link_%x",fs
->pid
);
1067 res
= rpc_call(func
,0,fs
->id
,src
,dest
);
1071 errno
= res
<0?-res
:0;
1072 return res
<0?-1:res
;
1075 int chown(const char *path
,uid_t uid
,gid_t gid
) {
1077 char *cpath
= getabsolutepath((char*)path
);
1078 struct fslist_item
*fs
= fsbypath(cpath
,0);
1082 asprintf(&func
,"fs_chown_%x",fs
->pid
);
1083 res
= rpc_call(func
,0,fs
->id
,cpath
,uid
,gid
);
1088 errno
= res
<0?-res
:0;
1089 return res
<0?-1:res
;
1092 int fchown(int fildes
,uid_t uid
,gid_t gid
) {
1094 struct filelist_item
*file
= filebyfh(fildes
);
1095 if (file
) res
= chown(file
->path
,uid
,gid
);
1097 errno
= res
<0?-res
:0;
1098 return res
<0?-1:res
;
1101 int chmod(const char *path
,mode_t mode
) {
1103 char *cpath
= getabsolutepath((char*)path
);
1104 struct fslist_item
*fs
= fsbypath(cpath
,0);
1108 asprintf(&func
,"fs_chmod_%x",fs
->pid
);
1109 res
= rpc_call(func
,0,fs
->id
,cpath
,mode
);
1114 errno
= res
<0?-res
:0;
1115 return res
<0?-1:res
;
1118 int fchmod(int fildes
,mode_t mode
) {
1120 struct filelist_item
*file
= filebyfh(fildes
);
1122 res
= chmod(file
->path
,mode
);
1123 if (res
==0) file
->mode
= mode
;
1126 errno
= res
<0?-res
:0;
1127 return res
<0?-1:res
;
1130 int utime(const char *path
,const struct utimbuf
*times
) {
1134 char *cpath
= getabsolutepath(path
);
1135 struct fslist_item
*fs
= fsbypath(cpath
,0);
1138 int shmid
= shmget(IPC_PRIVATE
,SHMMEM_SIZE
,0);
1139 shmbuf
= shmat(shmid
,NULL
,0);
1141 asprintf(&func
,"fs_utime_%x",fs
->pid
);
1142 strncpy(shmbuf
,path
,SHMMEM_SIZE
);
1143 memcpy(shmbuf
+strlen(shmbuf
)+1,times
,sizeof(struct utimbuf
));
1144 res
= rpc_call(func
,0,fs
->id
,shmid
);
1147 shmctl(shmid
,IPC_RMID
,NULL
);
1153 errno
= res
<0?-res
:0;
1154 return res
<0?-1:res
;
1157 mode_t
umask(mode_t cmask
) {
1158 mode_t ret
= creation_mask
;
1159 creation_mask
= cmask
&0777;
1163 ///////// SOCKET STUFF /////////////////////
1165 int socket(int domain
,int type
, int protocol
) {