stdlibc: small changes
[meinos.git] / apps / lib / stdlibc / files.c
blob1d0ffef0116198c181431b5ef8eb67b942fdebcd
1 /*
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>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <llist.h>
23 #include <errno.h>
24 #include <stdarg.h>
25 #include <rpc.h>
26 #include <sys/ipc.h>
27 #include <sys/shm.h>
28 #include <limits.h>
29 #include <stdio.h>
30 #include <path.h>
31 #include <misc.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() (nextfh++)
44 #define SHMMEM_SIZE (2*PAGE_SIZE)
46 struct fslist_item {
47 pid_t pid;
48 id_t id;
49 path_t *mountpoint;
50 char *mountpoint_str;
53 struct filelist_item {
54 struct fslist_item *fs;
55 int fs_fh;
56 struct dirent dir_cur;
57 mode_t mode;
58 int oflag;
59 int fh;
60 char *path;
61 int shmid;
62 void *shmbuf;
63 enum { FL_FILE,FL_DIR,FL_PIPE,FL_SOCK } type;
64 /// @todo Check for right file types (e.g. in read()/write()) and set them in open()/opendir()/socket()
67 static llist_t filelist;
68 static llist_t fslist;
69 static int nextfh;
70 static struct {
71 char *str;
72 size_t strlen;
73 path_t *path;
74 } workdir;
75 static mode_t creation_mask;
76 struct process_data *_process_data;
78 /**
79 * Initializes File I/O
81 void _fs_init(char *_stdin,char *_stdout,char *_stderr) {
82 filelist = llist_create();
83 fslist = llist_create();
84 creation_mask = 0777;
86 // Init current workdir
87 char *path = getenv("PATH");
88 if (path==NULL) path = "/";
89 memset(&workdir,0,sizeof(workdir));
90 chdir(path);
92 // Create stdin, stdout, stderr
93 nextfh = STDIN_FILENO;
94 if (_stdin!=NULL) open(_stdin,O_RDONLY);
95 nextfh = STDOUT_FILENO;
96 if (_stdout!=NULL) open(_stdout,O_WRONLY);
97 nextfh = STDERR_FILENO;
98 if (_stderr!=NULL) open(_stderr,O_WRONLY);
99 nextfh = STDERR_FILENO+1;
103 * Match mountpoint
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) {
109 size_t i,curcmp;
110 size_t maxcmp = 0;
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);
119 if (curcmp>maxcmp) {
120 maxcmp = curcmp;
121 maxfs = fs;
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,"/");
128 return maxfs;
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
135 * @return FSID
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);
140 if (fs==NULL) {
141 fs = malloc(sizeof(struct fslist_item));
142 char *mountpoint = strdup(path);
143 fs->id = rpc_call("vfs_getfsid",1,path,parent);
144 if (fs->id<0) {
145 free(mountpoint);
146 errno = -fs->id;
147 return NULL;
149 mountpoint[strlen(mountpoint)-strlen(path)] = 0;
150 fs->mountpoint = path_parse(mountpoint);
151 fs->mountpoint_str = path_output(fs->mountpoint,NULL);
152 free(mountpoint);
153 fs->pid = rpc_call("vfs_getpid",0,fs->id);
154 if (fs->pid<0) {
155 errno = -fs->pid;
156 return NULL;
158 llist_push(fslist,fs);
161 return fs;
165 * Gets list index by filehandle
166 * @param fh filehandle
167 * @return List index
169 static int lidxbyfh(int fh) {
170 struct filelist_item *file;
171 int i;
172 for (i=0;(file = llist_get(filelist,i));i++) {
173 if (file->fh==fh) return i;
175 return -1;
178 static struct filelist_item *filebyfh(int fh) {
179 if (fh>=0) {
180 int idx = lidxbyfh(fh);
181 if (idx>=0) return llist_get(filelist,idx);
183 return NULL;
187 * Gets absolute path by relative path
188 * @param relative Relative or absolute path
189 * @return Absolute path (Can be passed to free())
191 static char *getabsolutepath(const char *relative) {
192 path_t *path = path_parse(relative);
193 if (!path->root) {
194 path_t *newpath = path_cat(workdir.path,path);
195 path_destroy(path);
196 path = newpath;
198 path_reject_dots(path);
199 return path_output(path,NULL);
203 * Gets current workdir
204 * @param buf Buffer to store path in
205 * @param size Size of buffer
206 * @return Current workdir
208 char *getcwd(char *buf,size_t size) {
209 if (buf==NULL) {
210 size = workdir.strlen+1;
211 buf = malloc(size);
213 else if (size==0) {
214 errno = EINVAL;
215 return NULL;
217 else if (workdir.strlen+1>size) {
218 errno = ERANGE;
219 return NULL;
221 return strncpy(buf,workdir.str,size);
225 * Change current workdir
226 * @param new New workdir
227 * @return 0=success; -1=failure
229 int chdir(const char *new) {
230 new = getabsolutepath((char*)new);
231 if (new==NULL) new = "/";
233 DIR *dir = opendir(new);
234 if (dir!=NULL) {
235 closedir(dir);
236 free(workdir.str);
237 path_destroy(workdir.path);
238 workdir.path = path_parse(new);
239 path_reject_dots(workdir.path);
240 workdir.str = path_output(workdir.path,NULL);
241 workdir.strlen = strlen(workdir.str);
242 setenv("PATH",workdir.str,1);
243 return 0;
245 else return -1;
249 * Change current workdir
250 * @param new Filedescriptor of new workdir
251 * @return 0=success; -1=failure
253 int fchdir(int fildes) {
254 int res;
255 struct filelist_item *file = filebyfh(fildes);
256 if (file!=NULL) res = chdir(file->path);
257 else res = -EBADF;
258 errno = res<0?-res:0;
259 return res<0?-1:res;
263 * Creates a new node
264 * @param path Path to new node
265 * @param mode Mode of new node
266 * @param dev DeviceID (not used)
267 * @return 0=success; -1=failure
269 int mknod(const char *path,mode_t mode,dev_t dev) {
270 int res;
271 char *cpath = getabsolutepath((char*)path);
272 struct fslist_item *fs = fsbypath(cpath,1);
273 char *func;
275 if (fs!=NULL) {
276 asprintf(&func,"fs_mknod_%x",fs->pid);
277 res = rpc_call(func,0,fs->id,cpath,mode&(~creation_mask),dev);
278 free(func);
280 else res = -EINVAL;
281 free(cpath);
282 errno = res<0?-res:0;
283 return res<0?-1:res;
287 * Checks whether file can be opened with mode
288 * @param path Path to file
289 * @param amode Mode
290 * @return 0=success; -1=failure
292 int access(const char *path,int amode) {
293 int res;
294 char *cpath = getabsolutepath((char*)path);
295 struct fslist_item *fs = fsbypath(cpath,0);
296 char *func;
298 if (fs!=NULL) {
299 asprintf(&func,"fs_access_%x",fs->pid);
300 res = rpc_call(func,0,fs->id,cpath,amode);
301 free(func);
303 else res = -EINVAL;
304 free(cpath);
305 errno = res<0?-res:0;
306 return res<0?-1:res;
310 * Opens a file
311 * @param path Path to file
312 * @param oflag Mode
314 int open(const char *path,int oflag,...) {
315 va_list args;
316 int fh = 0;
317 void *shmbuf;
318 char *func;
319 char *cpath = getabsolutepath(path);
320 struct fslist_item *fs = fsbypath(cpath,0);
321 if (fs==NULL) fh = -errno;
323 va_start(args,oflag);
325 if (fh==0) {
326 if (oflag&O_CREAT) {
327 oflag &= ~O_CREAT;
328 int res = mknod(path,va_arg(args,mode_t)|S_IFREG,0);
329 if (res==-1 && errno!=EEXIST) fh = -errno;
331 int shmid = shmget(IPC_PRIVATE,SHMMEM_SIZE,0);
332 shmbuf = shmat(shmid,NULL,0);
333 if (shmbuf!=NULL) {
334 strncpy(shmbuf,cpath,SHMMEM_SIZE);
335 asprintf(&func,"fs_open_%x",fs->pid);
336 fh = rpc_call(func,0,fs->id,oflag,shmid);
337 free(func);
338 if (fh>=0) {
339 struct filelist_item *new = malloc(sizeof(struct filelist_item));
340 new->fs_fh = fh;
341 new->fs = fs;
342 new->oflag = oflag;
343 new->mode = S_IFREG;
344 new->fh = getnew_fh();
345 new->path = strdup(cpath);
346 new->shmid = shmid;
347 new->shmbuf = shmbuf;
348 fh = new->fh;
349 llist_push(filelist,new);
353 va_end(args);
354 free(cpath);
355 errno = fh<0?-fh:0;
356 return fh<0?-1:fh;
360 * Closes all filehandles
362 void _close_all_filehandles() {
363 struct filelist_item *file;
364 while ((file = llist_pop(filelist))!=NULL) {
365 if (S_ISREG(file->mode)) close(file->fh);
366 else if (S_ISDIR(file->mode)) closedir(file);
371 * Closes a file
372 * @param fildes File descriptor
373 * @return 0=success; -1=failure
375 int close(int fildes) {
376 int res;
377 char *func;
378 struct filelist_item *file = filebyfh(fildes);
379 if (file) {
380 asprintf(&func,"fs_close_%x",file->fs->pid);
381 res = rpc_call(func,0,file->fs->id,file->fs_fh);
382 free(func);
383 if (res==0) {
384 shmdt(file->shmbuf);
385 shmctl(file->shmid,IPC_RMID,NULL);
386 llist_remove(filelist,lidxbyfh(fildes));
387 free(file->path);
388 free(file);
391 else res = -EBADF;
392 errno = res<0?-res:0;
393 return res<0?-1:res;
394 return -1;
398 * Duplicates a file descriptor
399 * @param fildes File descriptor
400 * @param fildes2 New file descriptor
401 * @return New file desciptor
403 int dup2(int fildes,int fildes2) {
404 int res = -1;
405 char *func;
406 struct filelist_item *file = filebyfh(fildes);
407 if (file) {
408 asprintf(&func,"fs_close_%x",file->fs->pid);
409 res = rpc_call(func,0,file->fs->id,file->fs_fh);
410 free(func);
411 if (res>=0) {
412 struct filelist_item *new = malloc(sizeof(struct filelist_item));
413 memcpy(new,file,sizeof(struct filelist_item));
414 if (fildes2==0) new->fh = getnew_fh();
415 else {
416 close(fildes2);
417 new->fh = fildes2;
419 new->fs_fh = res;
420 new->shmid = shmget(IPC_PRIVATE,SHMMEM_SIZE,0);
421 new->shmbuf = shmat(new->shmid,NULL,0);
422 llist_push(filelist,new);
425 else errno = EBADF;
426 return res;
430 * Reads from a file
431 * @param fildes File descriptor
432 * @param buf Buffer to store read data in
433 * @param count How many bytes to read
434 * @return How many bytes read
436 static ssize_t _read(struct filelist_item *file,void *buf,size_t count) {
437 ssize_t res;
438 char *func;
439 asprintf(&func,"fs_read_%x",file->fs->pid);
440 res = rpc_call(func,0,file->fs->id,file->fs_fh,count);
441 free(func);
442 if (res>0) memcpy(buf,file->shmbuf,res);
443 return res;
445 ssize_t read(int fildes,void *buf,size_t count) {
446 struct filelist_item *file = filebyfh(fildes);
447 if (file!=NULL) {
448 ssize_t count_rem = count;
449 size_t off = 0;
451 while (count_rem>0) {
452 size_t count_cur = count_rem;
453 if (count_cur>SHMMEM_SIZE) count_cur = SHMMEM_SIZE;
454 count_cur = _read(file,buf+off,count_cur);
455 if (count_cur==-1) return -1;
456 count_rem -= count_cur;
457 if (count_cur==0) break;
458 off += count_cur;
461 return count-count_rem;
463 else {
464 errno = EBADF;
465 return -1;
470 * Writes to a file
471 * @param fildes File descriptor
472 * @param buf Data to write to file
473 * @param count How many bytes to write
474 * @return How many bytes written
476 static ssize_t _write(struct filelist_item *file,const void *buf,size_t count) {
477 char *func;
478 ssize_t res;
479 memcpy(file->shmbuf,buf,count);
480 asprintf(&func,"fs_write_%x",file->fs->pid);
481 res = rpc_call(func,0,file->fs->id,file->fs_fh,count);
482 free(func);
483 return res;
485 ssize_t write(int fildes,const void *buf,size_t count) {
486 struct filelist_item *file = filebyfh(fildes);
487 if (file!=NULL) {
488 ssize_t count_rem = count;
489 size_t off = 0;
490 while (count_rem>0) {
491 size_t count_cur = count_rem;
492 if (count_cur>SHMMEM_SIZE) count_cur = SHMMEM_SIZE;
493 count_cur = _write(file,buf+off,count_cur);
494 if (count_cur==-1) return -1;
495 count_rem -= count_cur;
496 if (count_cur==0) break;
497 off += count_cur;
499 return count-count_rem;
501 else {
502 errno = EBADF;
503 return -1;
508 * Seeks in a file
509 * @param fildes File descriptor
510 * @param offset Offset
511 * @param whence SEEK_SET, SEEK_CUR, SEEK_END
512 * @return New position
514 off_t lseek(int fildes,off_t offset,int whence) {
515 int res;
516 char *func;
517 struct filelist_item *file = filebyfh(fildes);
518 if (file!=NULL) {
519 asprintf(&func,"fs_seek_%x",file->fs->pid);
520 res = rpc_call(func,0,file->fs->id,file->fs_fh,offset,whence);
521 free(func);
523 else res = -EBADF;
524 errno = res<0?-res:0;
525 return res<0?-1:res;
529 * Removes a file
530 * @param path Path to file
531 * @return 0=success; -1=failure
533 int unlink(const char *path) {
534 int res;
535 char *cpath = getabsolutepath((char*)path);
536 struct fslist_item *fs = fsbypath(cpath,1);
537 char *func;
539 if (fs!=NULL) {
540 asprintf(&func,"fs_unlink_%x",fs->pid);
541 res = rpc_call(func,0,fs->id,cpath);
542 free(func);
544 else res = -EINVAL;
545 free(cpath);
546 errno = res<0?-res:0;
547 return res<0?-1:res;
551 * Removes a directory
552 * @param path Path to directory
553 * @return 0=success; -1=failure
555 int rmdir(const char *path) {
556 int res;
557 char *cpath = getabsolutepath((char*)path);
558 struct fslist_item *fs = fsbypath(cpath,1);
559 char *func;
561 if (fs!=NULL) {
562 asprintf(&func,"fs_rmdir_%x",fs->pid);
563 res = rpc_call(func,0,fs->id,cpath);
564 free(func);
566 else res = -EINVAL;
567 free(cpath);
568 errno = res<0?-res:0;
569 return res<0?-1:res;
573 * Renames a file
574 * @param path Path to directory
575 * @return 0=success; -1=failure
577 int rename(const char *old, const char *new) {
578 int res;
579 char *cold = getabsolutepath((char*)old);
580 char *cnew = getabsolutepath((char*)new);
581 struct fslist_item *fs = fsbypath(cold,1);
582 struct fslist_item *fsnew = fsbypath(cnew,1);
583 char *func;
585 if (fs!=NULL && fs==fsnew) {
586 asprintf(&func,"fs_rename_%x",fs->pid);
587 res = rpc_call(func,0,fs->id,old,new);
588 free(func);
590 else res = -EINVAL;
591 errno = res<0?-res:0;
592 return res<0?-1:res;
596 * Truncates a file
597 * @param path Path
598 * @param length New length
599 * @return 0=success; -1=failure
601 int truncate(const char *path,off_t length) {
602 int fh;
603 int res = -1;
604 if ((fh = open(path,O_WRONLY))!=-1) {
605 if (ftruncate(fh,length)!=-1) res = 0;
606 close(fh);
608 return res;
612 * Truncates a file
613 * @param fildes File descriptor
614 * @param length New length
615 * @return 0=success; -1=failure
617 int ftruncate(int fildes,off_t length) {
618 int res;
619 char *func;
620 struct filelist_item *file = filebyfh(fildes);
621 if (file) {
622 asprintf(&func,"fs_ftruncate_%x",file->fs->pid);
623 res = rpc_call(func,0,file->fs->id,file->fs_fh,length);
624 free(func);
626 else res = -EBADF;
627 errno = res<0?-res:0;
628 return res<0?-1:res;
629 return -1;
633 * Opens a directory
634 * @param path Path to directory
635 * @return Pointer to dir handle
637 DIR *opendir(const char *path) {
638 int dh,res;
639 void *shmbuf;
640 char *func;
641 char *cpath = getabsolutepath(path);
642 struct fslist_item *fs = fsbypath(cpath,0);
644 struct filelist_item *new;
645 if (fs!=NULL) {
646 int shmid = shmget(IPC_PRIVATE,SHMMEM_SIZE,0);
647 shmbuf = shmat(shmid,NULL,0);
648 if (shmbuf!=NULL) {
649 strncpy(shmbuf,cpath,SHMMEM_SIZE);
650 asprintf(&func,"fs_opendir_%x",fs->pid);
651 dh = rpc_call(func,0,fs->id,shmid);
652 free(func);
653 if (dh>=0) {
654 new = malloc(sizeof(struct filelist_item));
655 new->fs_fh = dh;
656 new->fs = fs;
657 new->oflag = 0;
658 new->mode = S_IFDIR;
659 new->fh = 0; // Dir handles don't need IDs
660 new->path = strdup(cpath);
661 new->shmid = shmid;
662 new->shmbuf = shmbuf;
663 new->dir_cur.d_name = NULL;
664 llist_push(filelist,new);
665 res = 0;
667 else res = dh;
669 else res = -errno;
671 else res = -ENOENT;
672 free(cpath);
673 errno = res<0?-res:0;
674 return res<0?NULL:((DIR*)new);
678 * Closes a directory
679 * @param file Dirhandle
680 * @return Errorcode
682 int closedir(DIR *file) {
683 int res;
684 char *func;
685 if (file) {
686 asprintf(&func,"fs_closedir_%x",file->fs->pid);
687 res = rpc_call(func,0,file->fs->id,file->fs_fh);
688 free(func);
689 if (res==0) {
690 shmdt(file->shmbuf);
691 shmctl(file->shmid,IPC_RMID,NULL);
692 free(file->path);
693 free(file);
694 llist_remove(filelist,llist_find(filelist,file));
697 else res = -EBADF;
698 errno = res<0?-res:0;
699 return res<0?-1:res;
703 * Reads an entry from an opened dir
704 * @param dh Dirhandle
705 * @return Direntry
707 struct dirent *readdir(DIR *file) {
708 int res;
709 char *func;
710 if (file!=NULL) {
711 asprintf(&func,"fs_readdir_%x",file->fs->pid);
712 res = rpc_call(func,0,file->fs->id,file->fs_fh);
713 free(func);
714 if (res>=0) {
715 if (file->dir_cur.d_name!=NULL) free(file->dir_cur.d_name);
716 file->dir_cur.d_name = strdup(file->shmbuf);
719 else res = -EBADF;
720 errno = res<0 && res!=-ENOENT?-res:0;
721 return res<0?NULL:&(file->dir_cur);
725 * Seeks in dir
726 * @param dh Dirhandle
727 * @param loc Location to seek to
729 void seekdir(DIR *file,long loc) {
730 int res;
731 char *func;
732 if (file) {
733 asprintf(&func,"fs_seekdir_%x",file->fs->pid);
734 res = rpc_call(func,0,file->fs->id,file->fs_fh,loc);
735 free(func);
737 else res = -EBADF;
738 errno = res<0?-res:0;
742 * Gets location in dir
743 * @param dh Dirhandle
744 * @return Location in dir
746 long telldir(DIR *file) {
747 int res;
748 char *func;
749 if (file) {
750 asprintf(&func,"fs_seekdir_%x",file->fs->pid);
751 res = rpc_call(func,0,file->fs->id,file->fs_fh,-1);
752 free(func);
754 else res = -EBADF;
755 errno = res<0?-res:0;
756 return res<0?-1:res;
760 * Gets informations about a file
761 * @param path Path to file
762 * @param buf Pointer to stat structure
763 * @return 0=success; -1=failure
765 int stat(const char *path,struct stat *buf) {
766 int fh;
767 int ret = -1;
768 if ((fh = open(path,O_RDONLY))!=-1) {
769 ret = fstat(fh,buf);
770 close(fh);
772 else {
773 struct filelist_item *dir = opendir(path);
774 if (dir!=NULL) {
775 ret = fstat(dir->fh,buf);
776 closedir(dir);
779 return ret;
783 * Gets informations about a filedescriptor
784 * @param fildes Filedescriptor
785 * @param buf Pointer to stat structure
786 * @return 0=success; -1=failure
788 int fstat(int fildes,struct stat *buf) {
789 int res;
790 char *func;
791 struct filelist_item *file = filebyfh(fildes);
792 if (file) {
793 asprintf(&func,"fs_fstat_%x",file->fs->pid);
794 res = rpc_call(func,0,file->fs->id,file->fs_fh);
795 memcpy(buf,file->shmbuf,sizeof(struct stat));
796 free(func);
798 else res = -EBADF;
799 errno = res<0?-res:0;
800 return res<0?-1:res;
804 * Gets informations about a filesystem
805 * @param path File included in FS of that information is wanted
806 * @param buf Pointer to statvfs structure
809 int statvfs(const char *path,struct statvfs *buf) {
810 int res = 0;
811 void *shmbuf;
812 char *func;
813 char *cpath = getabsolutepath(path);
814 struct fslist_item *fs = fsbypath(cpath,0);
816 if (fs!=NULL) {
817 int shmid = shmget(IPC_PRIVATE,SHMMEM_SIZE,0);
818 shmbuf = shmat(shmid,NULL,0);
819 if (shmbuf!=NULL) {
820 asprintf(&func,"fs_statvfs_%x",fs->pid);
821 memset(buf,0,sizeof(struct statvfs));
822 strncpy(shmbuf,cpath,SHMMEM_SIZE);
823 res = rpc_call(func,0,fs->id,shmid);
824 memcpy(buf,shmbuf,sizeof(struct statvfs));
825 free(func);
826 shmdt(shmbuf);
827 shmctl(shmid,IPC_RMID,NULL);
829 else res = -errno;
831 else res = -EBADF;
832 free(cpath);
833 errno = res<0?-res:0;
834 return res<0?-1:res;
838 * Reads link
839 * @param path Path to link
840 * @param buf Buffer for path
841 * @param bufsize Size of buffer
842 * @return Bytes written to buffer
844 ssize_t readlink(const char *path,char *buf,size_t bufsize) {
845 int res = 0;
846 void *shmbuf;
847 char *func;
848 char *cpath = getabsolutepath(path);
849 struct fslist_item *fs = fsbypath(cpath,0);
851 if (fs!=NULL) {
852 int shmid = shmget(IPC_PRIVATE,SHMMEM_SIZE,0);
853 shmbuf = shmat(shmid,NULL,0);
854 if (shmbuf!=NULL) {
855 asprintf(&func,"fs_readlink_%x",fs->pid);
856 strncpy(shmbuf,cpath,SHMMEM_SIZE);
857 res = rpc_call(func,0,fs->id,shmid,bufsize);
858 strncpy(buf,shmbuf,bufsize);
859 free(func);
860 shmdt(shmbuf);
861 shmctl(shmid,IPC_RMID,NULL);
863 else res = -errno;
865 else res = -EBADF;
866 free(cpath);
867 errno = res<0?-res:0;
868 return res<0?-1:res;
872 * Creates a symoblic link
873 * @param src Source file
874 * @param dest Destination (name of symlink)
875 * @return 0=success; -1=failure
877 int symlink(const char *dest,const char *src) {
878 int res;
879 char *csrc = getabsolutepath((char*)src);
880 char *cdest = getabsolutepath((char*)dest);
881 struct fslist_item *fs = fsbypath(csrc,1);
882 char *func;
884 if (fs!=NULL) {
885 asprintf(&func,"fs_symlink_%x",fs->pid);
886 res = rpc_call(func,0,fs->id,csrc,cdest);
887 free(func);
889 else res = -EINVAL;
890 errno = res<0?-res:0;
891 return res<0?-1:res;
895 * Creates a hardlink
896 * @param src Source file
897 * @param dest Destination (name of hardlink)
898 * @return 0=success; -1=failure
900 int link(const char *src,const char *dest) {
901 int res;
902 char *csrc = getabsolutepath((char*)src);
903 char *cdest = getabsolutepath((char*)dest);
904 struct fslist_item *fs = fsbypath(csrc,1);
905 struct fslist_item *fsdest = fsbypath(cdest,0);
906 char *func;
908 if (fs!=NULL && fs==fsdest) {
909 asprintf(&func,"fs_link_%x",fs->pid);
910 res = rpc_call(func,0,fs->id,src,dest);
911 free(func);
913 else res = -EINVAL;
914 errno = res<0?-res:0;
915 return res<0?-1:res;
918 int chown(const char *path,uid_t uid,gid_t gid) {
919 int res;
920 char *cpath = getabsolutepath((char*)path);
921 struct fslist_item *fs = fsbypath(cpath,0);
922 char *func;
924 if (fs!=NULL) {
925 asprintf(&func,"fs_chown_%x",fs->pid);
926 res = rpc_call(func,0,fs->id,cpath,uid,gid);
927 free(func);
929 else res = -EINVAL;
930 free(cpath);
931 errno = res<0?-res:0;
932 return res<0?-1:res;
935 int fchown(int fildes,uid_t uid,gid_t gid) {
936 int res;
937 struct filelist_item *file = filebyfh(fildes);
938 if (file) res = chown(file->path,uid,gid);
939 else res = -EBADF;
940 errno = res<0?-res:0;
941 return res<0?-1:res;
944 int chmod(const char *path,mode_t mode) {
945 int res;
946 char *cpath = getabsolutepath((char*)path);
947 struct fslist_item *fs = fsbypath(cpath,0);
948 char *func;
950 if (fs!=NULL) {
951 asprintf(&func,"fs_chmod_%x",fs->pid);
952 res = rpc_call(func,0,fs->id,cpath,mode);
953 free(func);
955 else res = -EINVAL;
956 free(cpath);
957 errno = res<0?-res:0;
958 return res<0?-1:res;
961 int fchmod(int fildes,mode_t mode) {
962 int res;
963 struct filelist_item *file = filebyfh(fildes);
964 if (file) {
965 res = chmod(file->path,mode);
966 if (res==0) file->mode = mode;
968 else res = -EBADF;
969 errno = res<0?-res:0;
970 return res<0?-1:res;
973 int utime(const char *path,const struct utimbuf *times) {
974 int res = 0;
975 void *shmbuf;
976 char *func;
977 char *cpath = getabsolutepath(path);
978 struct fslist_item *fs = fsbypath(cpath,0);
980 if (fs!=NULL) {
981 int shmid = shmget(IPC_PRIVATE,SHMMEM_SIZE,0);
982 shmbuf = shmat(shmid,NULL,0);
983 if (shmbuf!=NULL) {
984 asprintf(&func,"fs_utime_%x",fs->pid);
985 strncpy(shmbuf,path,SHMMEM_SIZE);
986 memcpy(shmbuf+strlen(shmbuf)+1,times,sizeof(struct utimbuf));
987 res = rpc_call(func,0,fs->id,shmid);
988 free(func);
989 shmdt(shmbuf);
990 shmctl(shmid,IPC_RMID,NULL);
992 else res = -errno;
994 else res = -EBADF;
995 free(cpath);
996 errno = res<0?-res:0;
997 return res<0?-1:res;
1000 mode_t umask(mode_t cmask) {
1001 mode_t ret = creation_mask;
1002 creation_mask = cmask&0777;
1003 return ret;
1006 ///////// SOCKET STUFF /////////////////////
1008 int socket(int domain,int type, int protocol) {
1009 return -1;