--- archive/podfuk.c.pavel.2.9 Tue Oct 26 09:59:00 1999 +++ podfuk.c Fri Oct 29 00:42:16 1999 @@ -48,9 +48,9 @@ # DEBUG turns on diagnostic printing # USE_MONITOR makes calls to an X progress bar -#CFLAGS = -DDEBUG -DUSE_MONITOR -Wall -#CFLAGS = -DDEBUG -DUSE_MONITOR -Wall -CFLAGS = -DDEBUG -Wall +CFLAGS = -DUSE_MONITOR -DCOREL_DEF -Wall +#CFLAGS = -DDEBUG -DUSE_MONITOR -DCOREL_DEF -Wall -g +#CFLAGS = -DDEBUG -Wall -DNODAEMON MIDNIGHT=/home/patb/projects/mc-4.5.40 @@ -63,10 +63,10 @@ all: podfuk podfuk: $(VFS)/libvfs.so podfuk.c - gcc podfuk.c `glib-config --libs --cflags` -I$(MIDNIGHT) -I$(KERNEL) -g $(VFS)/libvfs.so -o podfuk $(CFLAGS) + gcc podfuk.c `glib-config --libs --cflags` -I$(MIDNIGHT) -I$(KERNEL) $(VFS)/libvfs.so -o podfuk $(CFLAGS) podfuk-static: podfuk.c - gcc podfuk.c `glib-config --libs --cflags` -DNODAEMON -I$(MIDNIGHT) -I$(KERNEL) -g $(VFS)/tcputil.so $(VFS)/fish.so $(VFS)/ftpfs.so $(VFS)/mcfs.so $(VFS)/utilvfs.so $(VFS)/local.so $(VFS)/vfs.so $(VFS)/tar.so $(VFS)/sfs.so $(VFS)/names.so $(VFS)/container.so $(VFS)/extfs.so $(VFS)/util-alone.so $(VFS)/util.sor $(VFS)/utilunix.sor $(VFS)/direntry.so -o podfuk-static + gcc podfuk.c `glib-config --libs --cflags` -I$(MIDNIGHT) -I$(KERNEL) $(VFS)/tcputil.so $(VFS)/fish.so $(VFS)/ftpfs.so $(VFS)/mcfs.so $(VFS)/utilvfs.so $(VFS)/local.so $(VFS)/vfs.so $(VFS)/tar.so $(VFS)/sfs.so $(VFS)/names.so $(VFS)/container.so $(VFS)/extfs.so $(VFS)/util-alone.so $(VFS)/util.sor $(VFS)/utilunix.sor $(VFS)/direntry.so -o podfuk-static $(CFLAGS) /dev/cfs0: mknod /dev/cfs0 c 67 5 @@ -133,6 +133,7 @@ #include #include #include +#include #include #include #include @@ -151,7 +152,7 @@ #define PARANOIA 1 -#define VERSION_STRING "2.9" +#define VERSION_STRING "2.9.1" #ifdef DEBUG # define DEBUG_PRINT printf @@ -161,6 +162,12 @@ # define FLUSH_TIME 300 #endif +#if COREL_DEF +# define MOUNT_POINT_STRING "/mnt/.mcvfs" +#else +# define MOUNT_POINT_STRING "/overlay" +#endif + /* There is nothing magic about these constants. I just selected them * so that kernel does not complain too loudly. */ #define MY_VOL 0x01234567 @@ -171,7 +178,8 @@ /* missing from vfs.h */ vfs * vfs_rosplit (char *path); extern int ftpfs_use_passive_connections; - int ftpfs_login_timeout = 10; +extern int ftpfs_retry_seconds; + /* our handle to the pipe */ int cfs; @@ -194,7 +202,6 @@ /* a linked list of the above objects */ GList *pList; -int bListLocked = 0; int count = 0; @@ -215,15 +222,12 @@ exit(0); } -void alarm_handler(int signo) +void flush_VFids(void) { GList *pWalk, *pPrev; struct coda_purgefid_out cmd; - /* should this be wrapped in a semaphore? YES */ - if (bListLocked) return; - DEBUG_PRINT( "cleaning the local VFid cache\n" ); /* note: we are deleting elements, so we have to walk carefully */ /* walk backward so that we purge children, then parents */ @@ -259,9 +263,19 @@ if ( !strcmp( var, "logfile" ) && val[0] ) { ftpfs_set_debug( val ); printf("logfile set to %s\n",val); } if ( !strcmp( var, "ftpfs_login_timeout") ) - ftpfs_login_timeout = atoi(val); + ftpfs_retry_seconds = atoi(val); } +#if GLIB_MINOR_VERSION==1 +inline char* g_strstrip(char*c) { + char *p; + for (p=c; *p && isspace(*p); p++); + memmove(c,p,strlen(p)+1); + for (p=c+strlen(c); p>c && isspace(p[-1]); p--); + *p = 0; + return c;} + +#endif /* load and parse an ini file: handles sections, comments and params */ void load_profile( const char* config_file, void (*setter) (const char*, const char*, const char*) ) @@ -276,16 +290,19 @@ p = g_strstrip(buf); if (p[0] == '[') { g_free(section); - section = g_strdup(g_strdelimit(p+1,"]",'\0')); + g_strdelimit(p+1,"]",'\0'); + section = g_strdup(p+1); //printf("got section header [%s]\n", section); } else if (p[0] == '#') { //printf("got a comment <%s>\n",p+1); } else { - char **pp; - pp = g_strsplit(buf,"=",1); - if (pp[0] && pp[1]) (*setter)( section, pp[0], pp[1] ); - //printf("got strings <%s> and <%s>\n",g_strstrip(pp[0]),pp[1] ? (g_strstrip(pp[1])) : ""); - g_strfreev(pp); + char *pp; + pp = strchr(buf,'='); + if (pp>buf && pp<(buf+strlen(buf)-1)) { + *pp=0; + (*setter)( section, g_strstrip(buf), g_strstrip(pp+1) ); + //printf("got strings <%s> and <%s>\n",buf,pp+1); + } } } g_free(section); @@ -296,9 +313,10 @@ #ifdef USE_MONITOR void progress_func( char* m) { - if (!monitor_handle) return; - /* You should better do text parsing in monitor */ - write(monitor_handle,m,strlen(m)); + if (monitor_handle==-1) return; + /* Send the progress string to the monitor. + * Add an extra zero to delimit the string. */ + write(monitor_handle,m,strlen(m)+1); } #endif // USE_MONITOR @@ -319,7 +337,7 @@ } if (!pWalk) { printf( "Bad handle passed %lx/%lx/%lx\n", id.Volume, id.Vnode, id.Unique ); - exit(1); + return 0; //exit(1); } } /* paranoia */ return ((struct v_list*)id.Unique)->real_name; @@ -547,7 +565,7 @@ int legal_name(char *name) { - if (!strncmp (name, "/overlay", 8) + if (!strncmp (name, MOUNT_POINT_STRING, strlen(MOUNT_POINT_STRING)) || (strchr(name, '#') && !vfs_rosplit(name))) return 0; return 1; @@ -557,6 +575,7 @@ main(int argc, char** argv) { char buf[2048]; + time_t time_last_msg = (time_t) 0x7fffffff; if (argc>1) { printf("%s: a virtual file system extention to Linux\n",argv[0]); @@ -583,14 +602,18 @@ DEBUG_PRINT( "Opened cfs0\n" ); #ifdef USE_MONITOR vfs_set_callback( CALL_INFO, progress_func ); - monitor_handle = open("/var/tmp/podfuk.pipe", O_WRONLY | O_NONBLOCK); + monitor_handle = open("/var/tmp/podfuk.pipe", O_RDWR | O_NONBLOCK); + if (monitor_handle==-1) + DEBUG_PRINT( "failed to open pipe to monitor\n" ); #endif load_profile( "/etc/podfukrc", set_global_var ); mc_vfs_init(); - signal(SIGTERM, signal_handler); + + signal(SIGTERM, signal_handler); /* graceful shutdown */ signal(SIGINT, signal_handler); + signal(SIGPIPE, SIG_IGN); /* pipe faults are benign */ + vfs_flags |= FL_ALWAYS_MAGIC; - #ifdef FL_NO_LOCALHASH vfs_flags |= FL_NO_LOCALHASH; /* Avoid local deadlock when someone accesses /#ahoj#utar */ #else @@ -613,7 +636,6 @@ struct timeval tv; int retval; - bListLocked = 0; /* Watch stdin (fd 0) to see when it has input. */ FD_ZERO(&rfds); FD_SET(cfs, &rfds); @@ -623,12 +645,19 @@ tv.tv_usec = 0; retval = select(cfs+1, &rfds, NULL, NULL, &tv); + /* onError */ if (retval == -1) { - if (errno == EINTR) - continue; printf( "select failed: %m\n" ); exit(1); } + /* onTimeout */ + if (retval == 0) { + if (time(NULL)-time_last_msg > FLUSH_TIME) { + flush_VFids(); + time_last_msg = (time_t) 0x7fffffff; /* only flush once */ + } + } + vfs_timeout_handler(); /* Don't rely on the value of tv now! */ @@ -636,8 +665,6 @@ if (msg == -1) continue; - bListLocked = 1; - DEBUG_PRINT( "got %3.3d byte command: opcode = %2.2ld ", msg, req->ih.opcode ); // printf( " (un=%d,pid=%d,pgid=%d) ", req.ih.unique, req.ih.pid, req.ih.pgid ); // printf( " (uid=%d,euid=%d,suid=%d,fsuid=%d) ",req.ih.cred.cr_uid,req.ih.cred.cr_euid,req.ih.cred.cr_suid,req.ih.cred.cr_fsuid ); @@ -655,6 +682,7 @@ #define DUMP_NAME(x) DEBUG_PRINT( "\n\tbase:%s\tname:%s\n\t", look_name(req->coda_##x.VFid), (char*)req + req->coda_##x.name); #define STAT(x) if (!legal_name(x)) {rep->oh.result = ENOENT; break; } else if (mc_lstat(x, &st) == -1) { rep->oh.result = errno; DEBUG_PRINT( "file %s probably does not exist.",x ); break; } #define BUILD_NAME(x) name = ((char*) req) + req->coda_##x.name; sprintf( buf, "%s/%s", look_name(req->coda_##x.VFid), name); +#define GET_VFID_name(x) if (NULL==(name=look_name(req->coda_##x.VFid))) {rep->oh.result = ENOENT; break;} switch (req->ih.opcode) { case CODA_ROOT: @@ -667,8 +695,8 @@ /********************* file props & access *******************/ case CODA_GETATTR: CMD(getattr); - DUMP(getattr); - name = look_name(req->coda_getattr.VFid); + DUMP(getattr); + GET_VFID_name(getattr); if (!v_created(req->coda_getattr.VFid)) { STAT(name); /* fills in st */ } else @@ -677,7 +705,8 @@ break; case CODA_SETATTR: CMD_NOREP(setattr); - name = look_name(req->coda_setattr.VFid); + DUMP(setattr); + GET_VFID_name(setattr); DEBUG_PRINT( " try to set mode to %o, mdate to %lx and owner to %d: ", req->coda_setattr.attr.va_mode, req->coda_setattr.attr.va_mtime.tv_sec, req->coda_setattr.attr.va_uid ); if ( req->coda_setattr.attr.va_mode != (u_short) -1) mc_chmod( name, req->coda_setattr.attr.va_mode ); @@ -687,10 +716,12 @@ /* this always returns TRUE; this seems to be ok with current CODA design */ CMD_NOREP(access); DUMP(access); DEBUG_PRINT( "flags:%x ", req->coda_access.flags ); + GET_VFID_name(access); break; case CODA_LOOKUP: /* !! ttd: search for existing VFid's instead of making many new ones */ CMD(lookup); DUMP_NAME(lookup); + GET_VFID_name(lookup); DEBUG_PRINT( "flags=%d: ", req->coda_lookup.flags ); BUILD_NAME(lookup); DEBUG_PRINT( "(stat: %s)", buf ); @@ -701,10 +732,11 @@ case CODA_READLINK: CMD(readlink); DUMP(readlink); + GET_VFID_name(readlink); /* put the string at the end of the structure * the reply packet must be smaller than the request packet */ - retval = mc_readlink(look_name(req->coda_readlink.VFid), + retval = mc_readlink(name, (char*)&rep + sizeof(rep->coda_readlink), msg - sizeof(rep->coda_readlink)); if (retval<=0) { @@ -720,7 +752,7 @@ case CODA_OPEN: CMD(open); DUMP(open); DEBUG_PRINT( "flags:%#x ", req->coda_open.flags ); - name = look_name(req->coda_open.VFid); + GET_VFID_name(open); if (!v_created(req->coda_open.VFid)) { STAT(name); } else @@ -736,10 +768,8 @@ if (!memcmp(name,"/#ftp:",6)) pName = strchr( name+1,'/' ); if (!pName) pName = name; - sprintf(monitor_buf,"PROG 0!NAME %s",pName); - /* blow away the ! */ - monitor_buf[6]=0; - write(monitor_handle, monitor_buf, strlen(monitor_buf+7)+7); + sprintf(monitor_buf,"NAME %s",pName); + write(monitor_handle, monitor_buf, strlen(monitor_buf+1)); } #endif name = get_local_copy(req->coda_open.VFid,req->coda_open.flags); @@ -755,7 +785,7 @@ case CODA_CLOSE: CMD_NOREP(close); DUMP(close); - name = look_name(req->coda_close.VFid); + GET_VFID_name(close); unget_local_copy(req->coda_close.VFid); DEBUG_PRINT( " the current VFid list has %d elements\n", g_list_length( pList ) ); // dump_vfid_list(); @@ -769,6 +799,7 @@ case CODA_CREATE: CMD(create); DUMP_NAME(create); + GET_VFID_name(create); BUILD_NAME(create); DEBUG_PRINT( "(create_name: %s)", buf ); rep->coda_create.VFid = alloc_vfid(buf); @@ -778,6 +809,7 @@ case CODA_MKDIR: CMD(mkdir); DUMP_NAME(mkdir); + GET_VFID_name(mkdir); BUILD_NAME(mkdir); DEBUG_PRINT( "(mkdir: %s)", buf ); if ( mc_mkdir( buf, req->coda_mkdir.attr.va_mode ) == 0) { @@ -791,6 +823,7 @@ case CODA_RMDIR: CMD_NOREP(rmdir); DUMP_NAME(rmdir); + GET_VFID_name(rmdir); BUILD_NAME(rmdir); DEBUG_PRINT( "(rmdir: %s)", buf ); if ( mc_rmdir( buf ) == 0) { @@ -802,6 +835,7 @@ case CODA_REMOVE: CMD_NOREP(remove); DUMP_NAME(remove); + GET_VFID_name(remove); BUILD_NAME(remove); DEBUG_PRINT( "(remove: %s)", buf ); if ( mc_unlink( buf ) == 0) { @@ -815,6 +849,10 @@ { char buf2[256]; name = ((char *) req) + req->coda_rename.srcname; + if (!name) { + rep->oh.result = ENOENT; + break; + } sprintf( buf, "%s/%s", look_name(req->coda_rename.sourceFid), name ); name = ((char *) req) + req->coda_rename.destname; sprintf( buf2, "%s/%s", look_name(req->coda_rename.destFid), name ); @@ -840,6 +878,8 @@ setegid (0); vfs_gid = 0; seteuid (0); vfs_uid = 0; + + time_last_msg = time(NULL); } /* while */ }