1 // Disable 64 bit indirections so we can override both functions.
2 #undef _LARGEFILE64_SOURCE
3 #undef _LARGEFILE_SOURCE
4 #undef _FILE_OFFSET_BITS
7 #include "renderfarm.h"
8 #include "renderfarmclient.h"
9 #include "renderfarmfsclient.h"
10 #include "renderfarmfsserver.h"
24 // These are hacks to get all the file I/O libraries to transparently
25 // go over the network without rewriting them.
37 RenderFarmFSClient *renderfarm_fs_global = 0;
40 // open doesn't seem overridable
41 // int open (__const char *path, int flags, ...)
43 // static int (*func)(__const char *__file, int __oflag) = 0;
45 // printf("open %s\n", path);
48 // func = (int(*)(const char *path, int flags))dlsym(RTLD_NEXT, "open");
50 // result = (*func)(path, flags);
55 FILE* fopen(const char *path, const char *mode)
57 static FILE* (*func)(const char *path, const char *mode) = 0;
58 // This pointer is meaningless except on the server.
62 func = (FILE*(*)(const char *path, const char *mode))dlsym(RTLD_NEXT, "fopen");
65 if(!strncmp(path, RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
67 renderfarm_fs_global->lock();
68 result = renderfarm_fs_global->fopen(path, mode);
69 renderfarm_fs_global->unlock();
72 result = (*func)(path, mode);
77 FILE* fopen64(const char *path, const char *mode)
79 static FILE* (*func)(const char *path, const char *mode) = 0;
80 // This pointer is meaningless except on the server.
84 func = (FILE*(*)(const char *path, const char *mode))dlsym(RTLD_NEXT, "fopen64");
87 if(!strncmp(path, RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
89 renderfarm_fs_global->lock();
90 result = renderfarm_fs_global->fopen(path, mode);
91 renderfarm_fs_global->unlock();
94 result = (*func)(path, mode);
101 int fclose(FILE *file)
103 static int (*func)(FILE *) = 0;
104 int result = 0, done = 0;
106 func = (int(*)(FILE *))dlsym(RTLD_NEXT, "fclose");
107 //printf("fclose\n");
109 if(renderfarm_fs_global)
111 renderfarm_fs_global->lock();
112 if(renderfarm_fs_global->is_open(file))
114 result = renderfarm_fs_global->fclose(file);
117 renderfarm_fs_global->unlock();
120 if(!done) result = (*func)(file);
124 int fileno (FILE *stream)
126 static int (*func)(FILE *) = 0;
129 func = (int(*)(FILE *))dlsym(RTLD_NEXT, "fileno");
130 if(renderfarm_fs_global)
132 renderfarm_fs_global->lock();
133 if(renderfarm_fs_global->is_open(stream))
135 result = renderfarm_fs_global->fileno(stream);
137 renderfarm_fs_global->unlock();
140 result = (*func)(stream);
144 // int fflush(FILE *file)
146 // static int (*func)(FILE *) = 0;
147 // int result = 0, done = 0;
149 // func = (int(*)(FILE *))dlsym(RTLD_NEXT, "fflush");
150 // //printf("fflush\n");
152 // renderfarm_fs_global->lock();
153 // if(renderfarm_fs_global->is_open(file))
155 // result = renderfarm_fs_global->fflush(file);
158 // renderfarm_fs_global->unlock();
160 // if(!done) result = (*func)(file);
164 int remove (__const char *__filename)
166 static int (*func)(__const char *) = 0;
169 func = (int(*)(__const char *))dlsym(RTLD_NEXT, "remove");
170 //printf("remove\n");
173 if(!strncmp(__filename, RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
175 renderfarm_fs_global->lock();
176 result = renderfarm_fs_global->remove(__filename);
177 renderfarm_fs_global->unlock();
180 result = (*func)(__filename);
185 int rename (__const char *__old, __const char *__new)
187 static int (*func)(__const char *, __const char *) = 0;
190 func = (int(*)(__const char *, __const char *))dlsym(RTLD_NEXT, "rename");
191 //printf("rename\n");
194 if(!strncmp(__old, RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
196 renderfarm_fs_global->lock();
197 result = renderfarm_fs_global->rename(__old, __new);
198 renderfarm_fs_global->unlock();
201 result = (*func)(__old, __new);
206 int fgetc (FILE *__stream)
208 static int (*func)(FILE *) = 0;
209 int result = 0, done = 0;
211 func = (int(*)(FILE *))dlsym(RTLD_NEXT, "fgetc");
214 if(renderfarm_fs_global)
216 renderfarm_fs_global->lock();
217 if(renderfarm_fs_global->is_open(__stream))
219 result = renderfarm_fs_global->fgetc(__stream);
222 renderfarm_fs_global->unlock();
225 if(!done) result = (*func)(__stream);
229 int getc (FILE *__stream)
231 return fgetc(__stream);
234 int fputc (int __c, FILE *__stream)
236 static int (*func)(int, FILE *) = 0;
237 int result = 0, done = 0;
239 func = (int(*)(int, FILE *))dlsym(RTLD_NEXT, "fputc");
242 if(renderfarm_fs_global)
244 renderfarm_fs_global->lock();
245 if(renderfarm_fs_global->is_open(__stream))
247 result = renderfarm_fs_global->fputc(__c, __stream);
250 renderfarm_fs_global->unlock();
253 if(!done) result = (*func)(__c, __stream);
257 int putc (int __c, FILE *__stream)
259 return fputc(__c, __stream);
262 size_t fread (void *__restrict __ptr, size_t __size,
263 size_t __n, FILE *__restrict __stream)
265 static int (*func)(void *, size_t, size_t, FILE *) = 0;
269 func = (int(*)(void *, size_t, size_t, FILE *))dlsym(RTLD_NEXT, "fread");
272 if(renderfarm_fs_global)
274 renderfarm_fs_global->lock();
275 if(renderfarm_fs_global->is_open(__stream))
277 result = renderfarm_fs_global->fread(__ptr, __size, __n, __stream);
280 renderfarm_fs_global->unlock();
283 if(!done) result = (*func)(__ptr, __size, __n, __stream);
288 size_t fwrite (__const void *__restrict __ptr, size_t __size,
289 size_t __n, FILE *__restrict __s)
291 static int (*func)(__const void *, size_t, size_t, FILE *) = 0;
295 func = (int(*)(__const void *, size_t, size_t, FILE *))dlsym(RTLD_NEXT, "fwrite");
297 if(renderfarm_fs_global)
299 renderfarm_fs_global->lock();
300 if(renderfarm_fs_global->is_open(__s))
302 result = renderfarm_fs_global->fwrite(__ptr, __size, __n, __s);
305 renderfarm_fs_global->unlock();
308 if(!done) result = (*func)(__ptr, __size, __n, __s);
313 int fseek (FILE *__stream, long int __off, int __whence)
315 static int (*func)(FILE *, long int, int) = 0;
319 func = (int(*)(FILE *, long int, int))dlsym(RTLD_NEXT, "fseek");
322 if(renderfarm_fs_global)
324 renderfarm_fs_global->lock();
325 if(renderfarm_fs_global->is_open(__stream))
327 result = renderfarm_fs_global->fseek(__stream, __off, __whence);
330 renderfarm_fs_global->unlock();
333 if(!done) result = (*func)(__stream, __off, __whence);
338 int fseeko64 (FILE *__stream, __off64_t __off, int __whence)
340 static int (*func)(FILE *, __off64_t, int) = 0;
344 func = (int(*)(FILE *, __off64_t, int))dlsym(RTLD_NEXT, "fseeko64");
345 //printf("fseeko64\n");
347 if(renderfarm_fs_global)
349 renderfarm_fs_global->lock();
350 if(renderfarm_fs_global->is_open(__stream))
352 result = renderfarm_fs_global->fseek(__stream, __off, __whence);
355 renderfarm_fs_global->unlock();
358 if(!done) result = (*func)(__stream, __off, __whence);
363 long int ftell (FILE *__stream)
365 static long int (*func)(FILE *) = 0;
369 func = (long int(*)(FILE *))dlsym(RTLD_NEXT, "ftell");
372 if(renderfarm_fs_global)
374 renderfarm_fs_global->lock();
375 if(renderfarm_fs_global->is_open(__stream))
377 result = renderfarm_fs_global->ftell(__stream);
380 renderfarm_fs_global->unlock();
383 if(!done) result = (*func)(__stream);
388 __off64_t ftello64 (FILE *__stream)
390 static __off64_t (*func)(FILE *) = 0;
391 __off64_t result = 0;
394 func = (__off64_t(*)(FILE *))dlsym(RTLD_NEXT, "ftello64");
396 if(renderfarm_fs_global)
398 renderfarm_fs_global->lock();
399 if(renderfarm_fs_global->is_open(__stream))
401 result = renderfarm_fs_global->ftell(__stream);
404 renderfarm_fs_global->unlock();
407 if(!done) result = (*func)(__stream);
410 return (*func)(__stream);
414 // Glibc inlines the stat functions and redirects them to __xstat functions
415 int __xstat (int __ver, __const char *__filename,
416 struct stat *__stat_buf)
418 static int (*func)(int __ver, __const char *__filename,
419 struct stat *__stat_buf) = 0;
421 // This pointer is meaningless except on the server.
425 func = (int(*)(int __ver, __const char *__filename,
426 struct stat *__stat_buf))dlsym(RTLD_NEXT, "__xstat");
429 if(!strncmp(__filename, RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
431 renderfarm_fs_global->lock();
432 result = renderfarm_fs_global->stat(__filename, __stat_buf);
433 renderfarm_fs_global->unlock();
437 result = (*func)(__ver, __filename, __stat_buf);
443 int __xstat64 (int __ver, __const char *__filename,
444 struct stat64 *__stat_buf)
446 static int (*func)(int __ver, __const char *__restrict __file,
447 struct stat64 *__restrict __buf) = 0;
448 // This pointer is meaningless except on the server.
452 func = (int(*)(int __ver, __const char *__restrict __file,
453 struct stat64 *__restrict __buf))dlsym(RTLD_NEXT, "__xstat64");
456 if(!strncmp(__filename, RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
458 renderfarm_fs_global->lock();
459 result = renderfarm_fs_global->stat64(__filename, __stat_buf);
460 renderfarm_fs_global->unlock();
463 result = (*func)(__ver, __filename, __stat_buf);
468 char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
470 static char* (*func)(char *__restrict __s, int __n, FILE *__restrict __stream) = 0;
474 func = (char*(*)(char *__restrict __s, int __n, FILE *__restrict __stream))dlsym(RTLD_NEXT, "fgets");
476 if(renderfarm_fs_global)
478 renderfarm_fs_global->lock();
479 if(renderfarm_fs_global->is_open(__stream))
481 result = renderfarm_fs_global->fgets(__s, __n, __stream);
484 renderfarm_fs_global->unlock();
487 if(!done) result = (*func)(__s, __n, __stream);
492 int fscanf (FILE *__restrict __stream,
493 __const char *__restrict __format, ...)
498 va_start(ap, __format);
500 if(renderfarm_fs_global)
502 renderfarm_fs_global->lock();
503 if(renderfarm_fs_global->is_open(__stream))
505 // Since this is currently only used in one place in dcraw, leave it blank.
506 // The future implementation may just read until the next \n and scan the string.
507 result = renderfarm_fs_global->fscanf(__stream, __format, ap);
510 renderfarm_fs_global->unlock();
513 if(!done) result = vfscanf(__stream, __format, ap);
539 RenderFarmFSClient::RenderFarmFSClient(RenderFarmClientThread *client)
541 mutex_lock = new Mutex("RenderFarmFSClient::mutex_lock");
542 this->client = client;
545 RenderFarmFSClient::~RenderFarmFSClient()
548 // Must not access filesystem until we get here
549 renderfarm_fs_global = 0;
552 void RenderFarmFSClient::initialize()
554 renderfarm_fs_global = this;
557 void RenderFarmFSClient::lock()
559 mutex_lock->lock("RenderFarmFSClient::lock");
562 void RenderFarmFSClient::unlock()
564 mutex_lock->unlock();
567 int RenderFarmFSClient::is_open(FILE *ptr)
569 for(int i = 0; i < files.total; i++)
570 if(files.values[i] == ptr) return 1;
574 void RenderFarmFSClient::set_open(FILE *ptr, int64_t pointer)
577 if(sizeof(FILE*) == 4)
578 pointers.append(pointer);
581 void RenderFarmFSClient::unset_open(FILE *ptr, int64_t pointer)
584 if(sizeof(FILE*) == 4)
585 pointers.remove(pointer);
588 int64_t RenderFarmFSClient::get_64(FILE *ptr)
590 if(sizeof(FILE*) == 4)
592 for(int i = 0; i < files.total; i++)
594 if(files.values[i] == ptr)
595 return pointers.values[i];
599 return Units::ptr_to_int64(ptr);
601 printf("RenderFarmFSClient::get_64 file %p not found\n", ptr);
606 FILE* RenderFarmFSClient::fopen(const char *path, const char *mode)
609 printf("RenderFarmFSClient::fopen 1\n");
610 int len = strlen(path) - strlen(RENDERFARM_FS_PREFIX) + strlen(mode) + 2;
611 char *buffer = new char[len];
614 strcpy(buffer, path + strlen(RENDERFARM_FS_PREFIX));
615 strcpy(buffer + strlen(buffer) + 1, mode);
618 client->lock("RenderFarmFSClient::fopen");
619 if(!client->send_request_header(RENDERFARM_FOPEN,
622 if(client->write_socket(buffer, len, RENDERFARM_TIMEOUT) == len)
624 unsigned char data[8];
625 if(client->read_socket((char*)data, 8, RENDERFARM_TIMEOUT) == 8)
627 file_int64 = READ_INT64(data);
628 file = (FILE*)Units::int64_to_ptr(file_int64);
633 if(file) set_open(file, file_int64);
637 printf("RenderFarmFSClient::fopen path=%s mode=%s file=%p\n", path, mode, file);
642 int RenderFarmFSClient::fclose(FILE *file)
645 unsigned char datagram[8];
647 int64_t file_int64 = get_64(file);
648 STORE_INT64(file_int64);
650 client->lock("RenderFarmFSClient::fclose");
651 if(!client->send_request_header(RENDERFARM_FCLOSE, 8))
653 if(client->write_socket((char*)datagram, 8, RENDERFARM_TIMEOUT) == 8)
661 unset_open(file, file_int64);
663 printf("RenderFarmFSClient::fclose file=%p\n", file);
667 int RenderFarmFSClient::fileno(FILE *file)
670 printf("RenderFarmFSClient::fileno file=%p\n", file);
672 unsigned char datagram[8];
674 int64_t file_int64 = get_64(file);
675 STORE_INT64(file_int64);
677 client->lock("RenderFarmFSClient::fileno");
678 if(!client->send_request_header(RENDERFARM_FILENO, 8))
680 if(client->write_socket((char*)datagram, 8, RENDERFARM_TIMEOUT) == 8)
682 unsigned char data[4];
683 if(client->read_socket((char*)data, 4, RENDERFARM_TIMEOUT) == 4)
685 result = READ_INT32(data);
695 printf("RenderFarmFSClient::fileno file=%p result=%d\n", file, result);
699 int RenderFarmFSClient::remove (__const char *__filename)
702 int len = strlen(__filename) + 1;
703 char *datagram = new char[len];
704 strcpy(datagram, __filename);
706 client->lock("RenderFarmFSClient::remove");
707 if(!client->send_request_header(RENDERFARM_REMOVE, len))
709 if(client->write_socket(datagram, len, RENDERFARM_TIMEOUT) != len)
720 printf("RenderFarmFSClient::remove path=%s\n", __filename);
724 int RenderFarmFSClient::rename (__const char *__old, __const char *__new)
727 int len = strlen(__old) + 1 + strlen(__new) + 1;
728 char *datagram = new char[len];
729 strcpy(datagram, __old);
730 strcpy(datagram + strlen(__old) + 1, __new);
732 client->lock("RenderFarmFSClient::rename");
733 if(!client->send_request_header(RENDERFARM_RENAME, len))
735 if(client->write_socket(datagram, len, RENDERFARM_TIMEOUT) != len)
746 printf("RenderFarmFSClient::remove old=%s new=%s\n", __old, __new);
750 int RenderFarmFSClient::fgetc (FILE *__stream)
753 printf("RenderFarmFSClient::fgetc 1\n");
755 unsigned char datagram[8];
757 int64_t file_int64 = get_64(__stream);
758 STORE_INT64(file_int64);
760 client->lock("RenderFarmFSClient::fgetc");
761 if(!client->send_request_header(RENDERFARM_FGETC, 8))
763 if(client->write_socket((char*)datagram, 8, RENDERFARM_TIMEOUT) != 8)
767 if(client->read_socket((char*)datagram, 1, RENDERFARM_TIMEOUT) != 1)
771 result = datagram[0];
779 printf("RenderFarmFSClient::fgetc file=%p result=%02x\n", __stream, result);
784 int RenderFarmFSClient::fputc (int __c, FILE *__stream)
787 printf("RenderFarmFSClient::fputc 1\n");
789 unsigned char datagram[9];
791 int64_t file_int64 = get_64(__stream);
792 STORE_INT64(file_int64);
795 client->lock("RenderFarmFSClient::fputc");
796 if(!client->send_request_header(RENDERFARM_FPUTC, 9))
798 if(client->write_socket((char*)datagram, 9, RENDERFARM_TIMEOUT) != 9)
807 printf("RenderFarmFSClient::fputc file=%p result=%02x\n", __stream, result);
812 int RenderFarmFSClient::fscanf(FILE *__restrict stream, const char *__restrict format, va_list ap)
814 char string[BCTEXTLEN];
815 fgets (string, BCTEXTLEN, stream);
819 char* RenderFarmFSClient::fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
823 unsigned char datagram[12];
825 int64_t file_int64 = get_64(__stream);
826 STORE_INT64(file_int64);
829 client->lock("RenderFarmFSClient::fgets");
830 if(!client->send_request_header(RENDERFARM_FGETS, 12))
832 if(client->write_socket((char*)datagram, 12, RENDERFARM_TIMEOUT) == 12)
834 // fgets bytes to follow
835 if(client->read_socket((char*)datagram, 4, RENDERFARM_TIMEOUT) == 4)
838 bytes = READ_INT32(datagram);
841 if(client->read_socket((char*)__s, bytes, RENDERFARM_TIMEOUT) == bytes)
853 printf("RenderFarmFSClient::fgets file=%p string=%p size=%d bytes=%p\n",
854 __stream, __s, bytes, bytes);
860 size_t RenderFarmFSClient::fread (void *__restrict __ptr, size_t __size,
861 size_t __n, FILE *__restrict __stream)
864 unsigned char datagram[16];
866 int64_t file_int64 = get_64(__stream);
867 STORE_INT64(file_int64);
871 client->lock("RenderFarmFSClient::fread");
872 if(!client->send_request_header(RENDERFARM_FREAD, 16))
874 if(client->write_socket((char*)datagram, 16, RENDERFARM_TIMEOUT) != 16)
879 if(client->read_socket((char*)datagram, 4, RENDERFARM_TIMEOUT) != 4)
884 result = READ_INT32(datagram);
885 if(client->read_socket((char*)__ptr, __size * result, RENDERFARM_TIMEOUT) !=
895 printf("RenderFarmFSClient::fread file=%p size=%d num=%d result=%d\n",
896 __stream, __size, __n, result);
901 size_t RenderFarmFSClient::fwrite (__const void *__restrict __ptr, size_t __size,
902 size_t __n, FILE *__restrict __s)
905 printf("RenderFarmFSClient::fwrite 1\n");
907 unsigned char datagram[16];
909 int64_t file_int64 = get_64(__s);
910 STORE_INT64(file_int64);
914 client->lock("RenderFarmFSClient::fwrite");
915 if(!client->send_request_header(RENDERFARM_FWRITE, 16))
917 if(client->write_socket((char*)datagram, 16, RENDERFARM_TIMEOUT) != 16)
922 if(client->write_socket((char*)__ptr, __size * __n, RENDERFARM_TIMEOUT) !=
928 if(client->read_socket((char*)datagram, 4, RENDERFARM_TIMEOUT) != 4)
932 result = READ_INT32(datagram);
941 printf("RenderFarmFSClient::fwrite file=%p size=%d num=%d result=%d\n",
942 __s, __size, __n, result);
947 int RenderFarmFSClient::fseek (FILE *__stream, int64_t __off, int __whence)
950 printf("RenderFarmFSClient::fseek 1\n");
952 unsigned char datagram[20];
954 int64_t file_int64 = get_64(__stream);
955 STORE_INT64(file_int64);
957 STORE_INT32(__whence);
959 // printf("RenderFarmFSClient::fseek %p %llx datagram=%02x%02x%02x%02x%02x%02x%02x%02x\n",
960 // __stream, file_int64, datagram[0], datagram[1], datagram[2], datagram[3], datagram[4], datagram[5], datagram[6], datagram[7]);
961 client->lock("RenderFarmFSClient::fseek");
962 if(!client->send_request_header(RENDERFARM_FSEEK, 20))
964 if(client->write_socket((char*)datagram, 20, RENDERFARM_TIMEOUT) != 20)
968 if(client->read_socket((char*)datagram, 4, RENDERFARM_TIMEOUT) != 4)
971 result = READ_INT32(datagram);
978 printf("RenderFarmFSClient::fseek stream=%p offset=%lld whence=%d result=%d\n",
979 __stream, __off, __whence, result);
983 int64_t RenderFarmFSClient::ftell (FILE *__stream)
986 unsigned char datagram[8];
988 int64_t file_int64 = get_64(__stream);
989 STORE_INT64(file_int64);
991 client->lock("RenderFarmFSClient::ftell");
992 if(!client->send_request_header(RENDERFARM_FTELL, 8))
994 if(client->write_socket((char*)datagram, 8, RENDERFARM_TIMEOUT) != 8)
998 if(client->read_socket((char*)datagram, 8, RENDERFARM_TIMEOUT) != 8)
1001 result = READ_INT64(datagram);
1008 printf("RenderFarmFSClient::fseek stream=%p result=%lld\n",
1013 int RenderFarmFSClient::stat (__const char *__restrict __file,
1014 struct stat *__restrict __buf)
1016 int len = strlen(__file) + 1;
1019 client->lock("RenderFarmFSClient::stat");
1020 if(!client->send_request_header(RENDERFARM_STAT, len))
1022 if(client->write_socket((char*)__file + strlen(RENDERFARM_FS_PREFIX), len, RENDERFARM_TIMEOUT) == len)
1024 if(client->read_socket((char*)__buf, sizeof(struct stat), RENDERFARM_TIMEOUT) == sizeof(struct stat))
1038 printf("RenderFarmFSClient::stat path=%s\n", __file);
1045 int RenderFarmFSClient::stat64 (__const char *__restrict __file,
1046 struct stat64 *__restrict __buf)
1048 int len = strlen(__file) + 1;
1050 bzero(__buf, sizeof(struct stat64));
1052 client->lock("RenderFarmFSClient::stat64");
1053 if(!client->send_request_header(RENDERFARM_STAT64, len))
1055 if(client->write_socket((char*)__file + strlen(RENDERFARM_FS_PREFIX), len, RENDERFARM_TIMEOUT) == len)
1058 if(client->read_socket((char*)&arg, sizeof(arg), RENDERFARM_TIMEOUT) == sizeof(arg))
1060 __buf->st_dev = arg.dev;
1061 // __buf->__st_ino = arg.ino32;
1062 __buf->st_ino = arg.ino;
1063 __buf->st_mode = arg.mode;
1064 __buf->st_nlink = arg.nlink;
1065 __buf->st_uid = arg.uid;
1066 __buf->st_gid = arg.gid;
1067 __buf->st_rdev = arg.rdev;
1068 __buf->st_size = arg.size;
1069 __buf->st_blksize = arg.blksize;
1070 __buf->st_blocks = arg.blocks;
1071 __buf->st_atim.tv_sec = arg.atim;
1072 __buf->st_mtim.tv_sec = arg.mtim;
1073 __buf->st_ctim.tv_sec = arg.ctim;
1085 printf("RenderFarmFSClient::stat64 path=%s\n", __file);