/****************************************************************************** * TMFSHook.cpp - description * ------------------- * begin : 2005/04/20 * copyright : (C) 2005 by Harald K. Strack * copyright : (C) 2005 by Trymedia Inc. * email : hstrack@trymedia.com ****************************************************************************** * changes name date comment * hks 2005/05/25 Mask support added. Revert fixed. * hks 2005/05/26 ap4 integrate support added. * hks 2005/06/26 Directory support added. */ /* TMFSHook: Trymedia FileSystem Hook * * This is an Adaptor (Wrapper) to hook P4's filesystem calls. * It only hooks (hopefully) calls for versioned files. Temporary files * are not hooked (see TMFSHook::CreateTemp()). * * It mainly does nothing, but if you need to add funcionality * to a filesytem call (like disabling Chmod(), ...) * you can do this in here or in the header file. * This class is used by TMClientUser and some of its subclasses. * * ******* DIRECTORY SUPPORT ************* * * To support directories this filesystem implementation hides them from * the p4 server: * * 1 If a filesystem is a directory it will be hidden from the realFS (see Set()) * * 2 For this filesystem a directory and a zero bytes file are the same! * They only differ in their unix st_mode (as it is...). * * 3 Reading (add, edit, submit) from a directory is redirected to a fake file, * with size 0. * * 4 Writing (sync, integrate, revert) is more complicated: * * 4.1 If a directory / 0-size-file does not exist on a client, this class * creates a 0-size-file and deletes it. This is easier than hooking out * open and write and so on... * TMBOSync::HandleDirectories decides then, based on the versioned * permissions of the directory / 0-size-file what kind of file is to create. * * 4.2 If a directory / 0-size-file exists on a client, p4 creates first * a tmp-file and renames this later on. In this case the * renaming is hooked out. Since the tmp-file is not renamed anymore * it will be deleted in Close(). * * 5 Deleting: like reading. * * This way ap4 won't complain about directories anymore. For the permission * and ownership implementation in the several handlers it does not matter * on what type of file they are working. */ #include "TMFSHook.h" /* Create a "real (p4) FileSys * */ TMFSHook * TMFSHook::Create (FileSysType type) { TMFSHook *tmp = new TMFSHook (type); tmp->realFS = FileSys::Create (type); return tmp; } /* Do not use this directly */ TMFSHook::TMFSHook ():FileSys () { tmbo = NULL; attr = 0; tools = TMTools::Instance (); dirPath = NULL; } /* Do not use this directly */ TMFSHook::TMFSHook (FileSysType type):FileSys () { tmbo = NULL; attr = 0; tools = TMTools::Instance (); dirPath = NULL; this->type = type; } TMFSHook::TMFSHook (const TMFSHook &) { this->dirPath = NULL; } FileSysType TMFSHook::GetType () { FileSysType tmp = realFS->GetType (); return tmp; } TMFSHook::~TMFSHook () { /* Delete a directory fake file: add does not use Close() */ if (this->dirPath != NULL) { tools->UnlinkFile (realFS->Path ().Text ()); delete this->dirPath; } delete this->realFS; } void TMFSHook::Open (FileOpenMode mode, Error * e) { realFS->Open (mode, e); //Hook for submit and integrate and add if (this->tmbo != NULL) { this->tmbo->SetFileSys (this); } } /* If we access a directory create a fake file. * = Let p4 think it would handle files. The * DIR_FAKE_SUFFIX has to be unique. If any file * like this really exists, you get problems. */ void TMFSHook::Set (const StrPtr & name) { /* Works only if the directory exists. If not * TMBOSync::HandleDirectories takes care */ if (tools->IsDirectory (name)) { StrBuf tmp; tmp << name << DIR_FAKE_SUFFIX; /* Sync and derivated need to write their fake data * into the fake file. I do not like upcasting! */ if (this->tmbo == NULL || this->tmbo->GetType () == SYNC_HANDLER || this->tmbo->GetType () == INTEG_HANDLER || this->tmbo->GetType () == REVERT_HANDLER) { this->path = tmp; } else { /* Submit add & edit need the real path here, * so their standard handlers can go on.*/ this->path = name; } /* All hooked operations need a file touched and * the realFS needs to work with this * fake file */ tools->TouchFile (tmp.Text ()); realFS->Set (tmp); /* Set the dirPath to let the destructor now, that we * are working on a fake file. It is nowhere else evaluated. */ this->dirPath = new StrBuf (); *this->dirPath << name; } else { /* Normal behaviour for files */ this->path = name; realFS->Set (name); } } void TMFSHook::Write (const char *buf, int len, Error * e) { realFS->Write (buf, len, e); } int TMFSHook::Read (char *buf, int len, Error * e) { int tmp = realFS->Read (buf, len, e); return tmp; } int TMFSHook::ReadLine (StrBuf * buf, Error * e) { int tmp = realFS->ReadLine (buf, e); return tmp; } /* Directories or nullfiles: are deleted here. The attached * Handler has to implement touching / creating as in TMBOSync::HandleDirecories * Only in case of sync an derivates. */ void TMFSHook::Close (Error * e) { realFS->Close (e); /* Delete the null file with the name of the directory: Sync and * inherited */ if (this->tmbo->GetType () == SYNC_HANDLER || this->tmbo->GetType () == INTEG_HANDLER || this->tmbo->GetType () == REVERT_HANDLER) { if (tools->IsNullFile (realFS->Path (), e)) { realFS->Unlink (e); } } } int TMFSHook::Stat () { int tmp = realFS->Stat (); return tmp; } int TMFSHook::StatModTime () { int tmp = realFS->StatModTime (); return tmp; } void TMFSHook::Truncate (Error * e) { realFS->Truncate (e); } void TMFSHook::Unlink (Error * e) { realFS->Unlink (e); } /* Generally Rename renames tmp-files to real files. * Directories or nullfiles: are not renamed = created here! * They are touched / created in TMBOSync::HandleDirecories * Only in case of sync an derivates */ void TMFSHook::Rename (FileSys * target, Error * e) { if (tools->IsNullFile (target->Path (), e)) { /* This space is for bugs */ } else { realFS->Rename (target, e); } } /* Hooked out for p4 edit, add, revert, sync, submit * The logic should be implemented in the Handlers. * */ void TMFSHook::Chmod (FilePerm perms, Error * e) { /* Edit, Submit Hook * Chmodding for Sync, Integ and Revert * is done TMBOSync::Run() */ //realFS->Chmod (perms,e); if (this->tmbo != NULL) { this->tmbo->Chmod (this, e); } } void TMFSHook::ChmodTime (Error * e) { realFS->ChmodTime (e); } /* String for errormessages */ StrBuf & TMFSHook::GetDescription () { StrBuf * buf = new StrBuf; buf->Set ("TRYMEDIA FS HOOK"); return *buf; } /* Get Unix permissions */ mode_t TMFSHook::GetMode (Error * e) { if (this->attr == 0) { attr = tools->GetAttr (path.Text (), e); if (attr == NULL) return 0; } return attr->st_mode; } /* Set Unix permissions */ void TMFSHook::SetMode (mode_t st_mode, Error * e) { tools->SetMode (path.Text (), st_mode, e); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#5 | 5056 | harald_strack |
Directory support. Serious bug concerned to not unzipped binaries removed. Some other small bugfixes. |
||
#4 | 4980 | harald_strack |
Since I am maintaining the stuff in a local repository, I did some copy errors in the last revisions. Fixed. |
||
#3 | 4978 | harald_strack |
ap4 integrate implemented. Octal format is now used to save permissions. NOT backwards compatible anymore!!! |
||
#2 | 4975 | harald_strack |
Permissions are now masked to 555, so no write is possible. If you edit the Makefile and give the parameter -DFULL_PERMS, you have the old behaviour. Bugfix in ap4 revert: Edited and changed files were not reverted correctly. |
||
#1 | 4948 | harald_strack | Initial revision. |