/****************************************************************************** * TMBOSync.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/26 SetFileSys disabled in this handler. * hks 2005/06/30 Directory support added. * hks 2005/07/31 chown to lchown changed (was bug). */ /* TMBOSync: Trymedia Handler for the ap4 sync command. * * This handler gets the versioned filenames (vpath)from * TMSyncClient::Message(). The filnames (path) it gets * from RecieveP4Attributes and a hook in TMClientUser. * The reason for this double way of getting filenames is * just to find coding errors. It helped a lot! * * With this data it can perform any actions an any files after the sync call. * */ #include "TMBOSync.h" TMBOSync::TMBOSync () : TMBO() { doNothing=false; } /* I start the processing here - just for fun */ TMBOSync::~TMBOSync () { Run (); } /* String for errormessages */ StrBuf & TMBOSync::GetDescription () { StrBuf * buf = new StrBuf; buf->Set (" TRYMEDIA SYNC HANDLER "); return *buf; } /* We do not need this funcionality here... */ void TMBOSync::SetFileSys (FileSys * fs) { } void TMBOSync::HandleArguments ( int argc, char **argv, Error * e ) { //Option processing Options opts; StrPtr * s = 0; ErrorId usage = { E_FAILED, "" }; opts.Parse( --argc, ++argv, "n", OPT_ANY, usage, e); if( (s = opts[ 'n' ]) ) { doNothing = true; } } /* Check the permissions of the file, if it is * a directory - create it or do nothing. When it * is really a null file, touch it, since it where * deleted in TMFSHook->close(). For a description how * directory handling works, see TMFSHook.cpp */ void TMBOSync::HandleDirectories (const StrPtr * name, mode_t st_mode, Error * e) { if (!tools->FileExists (name->Text ())) { if (S_ISDIR (st_mode)) { tools->Mkdir (name->Text ()); } else if (S_ISREG (st_mode)) { tools->TouchFile (name->Text ()); } else { cerr << GetDescription ().Text () << " ERROR: The path " << name-> Text () << " seems not to be a directory or file! Unsupported." << endl; } } } /* Iterates over all versioned filenames. * * Performs for every versioned filename a p4 fstat. * * The OutputStat() Method in TMClientUser is hooked * and sets the attributes (permission, uid, gid) to * the fileData * pointed by this->tmpNode (the actual node during * the Iteration). * * This is a poor interface to communicate, but who cares... * * It then uses the data (permission, uid, gid) to set them on the * file on the unix filesystem. * * */ void TMBOSync::Run (Error * e) { if (doNothing) return; //Start iteration tmpNode = head; while (tmpNode != NULL) { //the versioned path, worst case if (tmpNode->data->vpath == NULL) { cerr << GetDescription ().Text () << "Fatal: Corrupted node. Abort. Programming error. " << endl; exit (1); } StrBuf vpath = *(data->GetVPath (tmpNode)); //Load attributes from p4d if (RecieveP4Attributes (&vpath) != TM_SUCCESS) { cerr << "Fatal: Giving up." << endl; exit (1); } //The path, worst case if (data->GetPath (tmpNode) == NULL) { cerr << GetDescription ().Text () << "Fatal: Node has no path!? But a versioned path." "Programming error. Abort. " << endl; exit (1); } //The file may not have permissions, uid and gid. If one is missing, //the file will not be handled. if (data->GetPerm (tmpNode) == NULL) { cerr << GetDescription ().Text () << " Warning: Node " << data->GetPath (tmpNode)->Text () << " has no permissions set. Skipping." << endl; tmpNode = tmpNode->next; continue; } if (data->GetUid (tmpNode) == NULL) { cerr << GetDescription ().Text () << " Warning: Node " << data->GetPath (tmpNode)->Text () << " has no uid set. Skipping." << endl; tmpNode = tmpNode->next; continue; } if (data->GetGid (tmpNode) == NULL) { cerr << GetDescription ().Text () << " Warning: Node " << data->GetPath (tmpNode)->Text () << " has no gid set. Skipping." << endl; tmpNode = tmpNode->next; continue; } //Set the permissions //mode_t st_mode = (mode_t) data->GetPerm(tmpNode)->Atoi(); mode_t st_mode; sscanf (data->GetPerm (tmpNode)->Text (), "%o", &st_mode); //Directory versioning support HandleDirectories (data->GetPath (tmpNode), st_mode, e); #ifndef FULL_PERMS st_mode &= 0177555; #endif /* Skip this for symbolik links */ if (!S_ISLNK (st_mode)) { errno = 0; if ((chmod (data->GetPath (tmpNode)->Text (), st_mode)) != 0) { int tmp = errno; errno = 0; if (e != NULL) { SetErrorMsg (e, E_FATAL, "Fatal: %s: chmod: %s - %s\n", GetDescription ().Text (), data->GetPath (tmpNode)->Text (), strerror (tmp)); } else { cerr << "Fatal: " << GetDescription ().Text () << " chmod: " << data->GetPath (tmpNode)->Text () << " - " << strerror (tmp) << endl; } tmpNode = tmpNode->next; continue; } } //The uid char *pw_name = (char *) data->GetUid (tmpNode)->Text (); struct passwd *pwd; errno = 0; if ((pwd = getpwnam (pw_name)) == NULL) { int tmp = errno; errno = 0; if (e != NULL) { SetErrorMsg (e, E_FATAL, "Fatal: %s: getpwnam: %s - %s\n", GetDescription ().Text (), data->GetPath (tmpNode)->Text (), strerror (tmp)); } else { cerr << "Fatal: " << GetDescription ().Text () << " getpwnam: " << data->GetPath (tmpNode)->Text () << " - " << strerror (tmp) << endl; } tmpNode = tmpNode->next; continue; } //The gid char *gr_name = (char *) data->GetGid (tmpNode)->Text (); struct group *grp; errno = 0; if ((grp = getgrnam (gr_name)) == NULL) { int tmp = errno; errno = 0; if (e != NULL) { SetErrorMsg (e, E_FATAL, "Fatal: %s: getgrnam: %s - %s\n", GetDescription ().Text (), data->GetPath (tmpNode)->Text (), strerror (tmp)); } else { cerr << "Fatal: " << GetDescription ().Text () << " getgrnam: " << data->GetPath (tmpNode)->Text () << " - " << strerror (tmp) << endl; } tmpNode = tmpNode->next; continue; } /* Do not follow symbolic links (lchown) */ if ((lchown (data->GetPath (tmpNode)->Text (), pwd->pw_uid, grp->gr_gid)) != 0) { int tmp = errno; errno = 0; if (e != NULL) { SetErrorMsg (e, E_FATAL, "Fatal: %s: chown: %s - %s\n", GetDescription ().Text (), data->GetPath (tmpNode)->Text (), strerror (tmp)); } else { cerr << "Fatal: " << GetDescription ().Text () << " chown: " << data->GetPath (tmpNode)->Text () << " - " << strerror (tmp) << endl; } tmpNode = tmpNode->next; continue; } //Next Element tmpNode = tmpNode->next; } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#6 | 5069 | harald_strack |
ADDITIONAL command parameter handling introduced. ap4 sync -n is handled. Usually there is no need for handling any command specific parameters. Tests improved. |
||
#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. |