Logo Search packages:      
Sourcecode: condor version File versions  Download package

directory.h

/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#ifndef DIRECTORY_H
#define DIRECTORY_H

#include "condor_uid.h"
#include "stat_info.h"

#ifndef WIN32
#     include <dirent.h>
#endif


/** Class to iterate filenames in a subdirectory.  Given a subdirectory
      path, this class can iterate the names of the files in the directory,
      remove files, and/or
      report file access/modify/create times.  Also reports if
      the filename represents another subdirectory or not.  
      <p><b>Note:</b> This class does not recurse down into subdirectories
      except when calling the Remove_Current_File() or Remove_Entire_Directory()
      methods.
*/
00040 class Directory
{
public:

      /** Constructor.  Upon instantiation, the user 
            should call Next() to fetch information on the first file.  
            If a priv_state is specified, this priv_state will be used 
            whenever accessing the filesystem.
            @param dirpath The full path to the subdirectory to operate upon
            @param priv The priv_state used when accessing the filesystem.
            If set to PRIV_UNKNOWN, then the class will use 
            whatever priv_state is currently in effect.  If set to
            PRIV_ROOT, note all operations will be tried as both PRIV_ROOT
            and as PRIV_CONDOR, just in case the files are being accessed
            over NFS (where root gets mapped to nobody).
            @see Next()
            @see priv_state
      */
      Directory( const char *dirpath, priv_state priv = PRIV_UNKNOWN);

      /** Alternate Constructor.  Instead of passing in a pathname, 
            the caller can instantiate by using a StatInfo object (since
            in many cases, they've already got a copy of that object).
            This allows them to pass in more info, and to prevent us from
            re-doing the syscalls and other work to figure out things we'd
            like to know about the directory.  Otherwise, this constructor
            is just like the other, in terms of how to use the Directory
            object once it exists, the handling of priv states, etc.
            @param info Pointer to the StatInfo object to use for infor.
            @param priv The priv_state used when accessing the filesystem.
            @see Next()
            @see priv_state
            @see StatInfo
      */
      Directory( StatInfo *info, priv_state priv = PRIV_UNKNOWN);

      /// Destructor<p>
      ~Directory();

      /** Get full path to the directory as instantiated. */
00080       const char *GetDirectoryPath( void ) { return curr_dir; }

      /** Fetch information on the next file in the subdirectory and
            make it the 'current' file.
            @return The filename of the next file, or NULL if there are 
            no more files.  The filename returned is just the basename; call
            GetFullPath() to get the complete pathname.
            Do not free or delete this memory; the class handles all memory management. 
            <b>Warning:</b> This pointer is meaningless when the Directory object is deleted.
            @see GetFullPath()
      */
      const char* Next();

      /** Restart the iteration.  After calling Rewind(), the next 
            call to Next() will return the first file in the directory again.
            @return Always returns true (for now)
            @see Next()
      */
      bool Rewind();

      /** Find a entry with a given name.  Iterates through all entries in the
            directory until a match is found, or the end is reached.  If a match
            is found, the current entry matches it.  Note that this function
            rewind()s the directory object, and, by definition, changes the
            current entry pointer.
            @return true if a match is found, false if not.
            @see Next()
      */

      bool Find_Named_Entry( const char *name );

      /** Get last access time of current file.  If there is no current
          file, return 0.
            @return time in seconds since 00:00:00 UTC, January 1, 1970 */
00114       time_t GetAccessTime() { return curr ? curr->GetAccessTime() : 0; };

      /** Get last modification time of current file.  If there is no
          current file, return 0.
            @return time in seconds since 00:00:00 UTC, January 1, 1970 */
00119       time_t GetModifyTime() { return curr ? curr->GetModifyTime() : 0; };

      /** Get creation time of current file.  If there is no current
          file, return 0. 
            @return time in seconds since 00:00:00 UTC, January 1, 1970 */
00124       time_t GetCreateTime() { return curr ? curr->GetCreateTime() : 0; };

      /** Get size of current file.  If there is no current file, return 0.
            @return size of file in bytes */
00128       filesize_t GetFileSize() { return curr ? curr->GetFileSize() : 0; };

      /** Get mode of current file.  If there is no current file, return 0.
            @return permission mode of the current file
      */
00133       mode_t GetMode() { return curr ? curr->GetMode() : 0; };

      /** Get the size of all the files and all the files in all subdirectories,
            starting with the directory specified by the constructor.
            @return the size of bytes (if we receive an error trying to determine
            the size of any file, we consider that file to have a size of zero). */
      filesize_t GetDirectorySize();

      /** Get full path name to the current file.  If there is no current file,
            return NULL.
            @return file pathname of the file */
00144       const char* GetFullPath() { return curr ? curr->FullPath() : NULL; };

      /** Determine if the current file is the name of a subdirectory,
            or just a file.  If there is no current file, return false.
            (A Symbolic link that points to a directory will return true.)
            @return true if current file is a subdirectory name, false if not
      */
00151       bool IsDirectory() { return curr ? curr->IsDirectory() : false; };

      /** Determine if the current file is a symbolic link.
            @return true if current file is a symbolic link, false if not
      */
00156       bool IsSymlink() {return curr ? curr->IsSymlink() : false; }

      /** Remove the current file.  If the current file is a subdirectory,
          then the subdirectory (and all files beneath it) are removed.
            @return true on successful removal, otherwise false
      */
      bool Remove_Current_File( void );

      /** Remove the specified file.  If the given file is a subdirectory,
          then the subdirectory (and all files beneath it) are removed. 
            @param path The full path to the file to remove
            @return true on successful removal, otherwise false
      */
      bool Remove_Full_Path( const char *path );

      /** Remove the specified directory entry.  If the given file is a
            subdirectory, then the subdirectory (and all files beneath it)
            are removed. @param path The full path to the file to remove
            @return true on successful removal, otherwise false */
      bool Remove_Entry( const char* name );

      /** Remove the all the files and subdirectories in the directory
            specified by the constructor.  Upon success, the subdirectory
            will still exist, but will be empty.
            @return true on successful removal, otherwise false
      */
      bool Remove_Entire_Directory( void );


#ifndef WIN32

      /** Recursively change ownership of this directory and kids

      Implemented in terms of recursive_chown, see that for most
      up to date details.

      @see recursive_chown

      Changes ownership of path to the UID dst_uid, and GID dst_gid
      from the UID src_uid.  The directory and all files and
      directories within it are changed.  If a file is encountered
      that is not owned by src_uid or dst_uid, it is considered an
      error.

      On an error, a message is reported to dprintf(D_ALWAYS) and false
      is returned.  Otherwise true is returned.

      @param src_uid UID who is allowed to already own the file

      @param dst_uid UID to change the file's ownership to.  (Will
      silently skip a file already downed by this user)

      @param dst_gid GID to change the file's ownership to.

      @param non_root_okay Should we silently skip chown attempt and
      report success if this process isn't root?  chown only works if
      this process has root permissions.  If this process isn't root
      and non_root_okay is true (the default), this function will
      silently return true.  If this process isn't root and
      non_root_okay is false, this function will fail.
      */
      bool Recursive_Chown(uid_t src_uid, uid_t dst_uid, gid_t dst_gid,
            bool non_root_okay = true);


            /** Recursively walk through the directory tree and chmod()
                  any real directories (ignoring symlinks) to the given
                  mode.
                  NOTE: This will call Rewind(), so it is NOT safe to use
                  this during another iteration over the directory.
                  @param mode The file mode you want to set directories to
            */
      bool chmodDirectories( mode_t mode );

#endif /* ! WIN32 */

      /** Recursively walk through the directory tree and change 
          the owner of all files and directories to the given 
          username.     
            @param username The username to that will owner.
            @param domain The domain of the user that will be the owner (on Win32).
       */
      bool Recursive_Chown(const char *username, const char *domain);


private:
      char *curr_dir;
      StatInfo* curr;
      bool want_priv_change;
      priv_state desired_priv_state;
      bool do_remove( const char *path, bool is_curr );
      bool do_remove_dir( const char *path );
      bool do_remove_file( const char *path );
      void initialize( priv_state priv );
      bool rmdirAttempt( const char* path, priv_state priv );

#ifdef WIN32
      long dirp;
      struct _finddata_t filedata;
#else
      DIR *dirp;
      priv_state setOwnerPriv( const char* path );
      uid_t owner_uid;
      gid_t owner_gid;
      bool owner_ids_inited;
#endif
};

// A handy utility class that deletes the underlying file
// when the class instance is deleted
class DeleteFileLater {
 public:
      DeleteFileLater (const char * _name) {
            filename = _name?strdup(_name):NULL;
      }

      ~DeleteFileLater () {
            if (filename) {
                  unlink(filename);
                  free (filename);
            }
      }
 protected:
      char * filename;
};


/** Determine if the given file is the name of a subdirectory,
  or just a file.
  @param path The full path to the file to test
  @return true if given file is a subdirectory name, false if not
*/
bool IsDirectory( const char* path );

/** Determine if the given file is the name of a symlink.
  @param path The full path to the file to test
  @return true if given file is a symlink, false if not
*/
bool IsSymlink( const char* path );

/** Take two strings, a directory path, and a filename, and
  concatenate them together.  If the directory path doesn't end with
  the appropriate directory deliminator for this platform, this
  function will ensure that the directory delimiter is included in the
  resulting full path.
  @param dirpath The directory path.
  @param filename The filename.
  @return A string created with new() that contains the full pathname.
*/
char* dircat( const char* dirpath, const char* filename );

/** Returns a path to subdirectory to use for temporary files.
  @return The pointer returned must be de-allocated by the caller w/ free()
*/
char* temp_dir_path();

#if ! defined(WIN32)
/** Recursively change ownership of a file or directory tree

Changes ownership of path to the UID dst_uid, and GID dst_gid
from the UID src_uid.  If path is a directory, the directory and
all files and directories within it are also changed.  If a file
is encountered that is not owned by src_uid or dst_uid, it is
considered an error.

On an error, a message is reported to dprintf(D_ALWAYS) and false
is returned.  Otherwise true is returned.

@param path File or directory to chown

@param src_uid UID who is allowed to already own the file

@param dst_uid UID to change the file's ownership to.  (Will
silently skip a file already downed by this user)

@param dst_gid GID to change the file's ownership to.

@param non_root_okay Should we silently skip chown attempt and
report success if this process isn't root?  chown only works if
this process has root permissions.  If this process isn't root
and non_root_okay is true (the default), this function will
silently return true.  If this process isn't root and
non_root_okay is false, this function will fail.
*/
bool recursive_chown(const char * path,
      uid_t src_uid, uid_t dst_uid, gid_t dst_gid, bool
      non_root_okay = true);

#endif /* ! defined(WIN32) */


char * create_temp_file();

/** Actual implementation of the recursive chown function that is called
    by the Directory::Recursive_Chown() member function. This function 
      can be called without firing up a whole directory object, if desired.
      @param path Path to be traversed recursively and chown'd
      @param username Username to chown to.
      @param domain Domain of the user to chown to.
*/
bool recursive_chown( const char *path, 
                                const char *username, const char *domain );
#endif

Generated by  Doxygen 1.6.0   Back to index