home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / lang / perl / 7558 / fileop.pl < prev   
Encoding:
Text File  |  1992-12-21  |  10.4 KB  |  331 lines

  1. ;# NAME
  2. ;#    fileop.pl - perl function(s) create, remove, copy, and change mode of 
  3. ;#          file system objects
  4. ;#
  5. ;# DESCRIPTION
  6. ;#    &Maybee_Delete_Path, &Create_Symlink, and &Create_Dir share 3 common 
  7. ;#    arguments: $Override_If_Link, $Override_If_File, and $Override_If_Dir.
  8. ;#    They have the following meaning where Path is the object that will be 
  9. ;#    created:
  10. ;#
  11. ;#       If Path is a link:
  12. ;#          + The operation will be forced if $Override_If_Link is TRUE
  13. ;#          + The operation will not be created otherwise
  14. ;#
  15. ;#       If Path is a file:
  16. ;#          + The operation will be forced if $Override_If_File is TRUE
  17. ;#          + The operation will not be created otherwise
  18. ;#
  19. ;#       If Path is a directory:
  20. ;#          + The operation will be forced if $Override_If_Dir is TRUE
  21. ;#          + The operation will not be created otherwise
  22. ;#
  23. ;#       If Path does not exist at all:
  24. ;#          + The directory will always be created
  25. ;#
  26. ;#    They all return the same thing, a ($Status, $Msg) pair where $status is:
  27. ;#
  28. ;#       -1     The action could not be performed because a condition for 
  29. ;#        the action was not met. $Msg tells why not.
  30. ;#
  31. ;#       0     The action could not be performed because of an error. $Msg 
  32. ;#        tells what happened.
  33. ;#
  34. ;#         1     The action was successfuly perfomed. $Msg tells what we did.
  35. ;#
  36. ;# AUTHOR
  37. ;#    Michael S. Muegel (mmuegel@mot.com)
  38. ;#
  39. ;# RCS INFORMATION
  40. ;#    $Author: mmuegel $
  41. ;#    $Header: /usr/local/ustart/src/perl-stuff/libs/fwrdc/misc/RCS/fileop.pl,v 1.6 1992/11/02 02:58:21 mmuegel Exp $
  42.  
  43. require "fileinfo.pl";
  44.  
  45. ;###############################################################################
  46. ;# Maybee_Delete_Path
  47. ;#
  48. ;# Deletes $Path depending on the Delete arguments. $Msg is a message
  49. ;# saying what deltion occured (null if none). $Type is set to "link", 
  50. ;# "directory", "file", or "" depending on whether $Path was any of them.
  51. ;# Finally, $Status is:
  52. ;#
  53. ;#   -1 if a deletion was necess. but failed
  54. ;#    0 if a delete was not necess
  55. ;#    1 if a delete was necess and succeeded
  56. ;#
  57. ;# Arguments:
  58. ;#    $Path, $Delete_If_Link, $Delete_If_File, $Delete_If_Dir
  59. ;#
  60. ;# Returns:
  61. ;#    $Status, $Type, $Msg
  62. ;###############################################################################
  63. sub Maybee_Delete_Path
  64. {
  65.    local ($Path, $Delete_If_Link, $Delete_If_File, $Delete_If_Dir) = @_;
  66.    local ($Type, $Msg);
  67.  
  68.    # Check for existing link
  69.    if (-l $Path)
  70.    {
  71.       $Type = "link";
  72.       return (-1, $Type, "$Path is already a link") if (! $Delete_If_Link);
  73.    } 
  74.  
  75.    # Need to isolate these, really...
  76.    else
  77.    {
  78.       # Check for existing file/directory
  79.       if (-d $Path)
  80.       {
  81.          $Type = "directory";
  82.          return (-1, $Type, "$Path is a directory") if (! $Delete_If_Dir);
  83.       };
  84.       if (-f _)
  85.       {
  86.          $Type = "file";
  87.          return (-1, $Type, "$Path is a file") if (! $Delete_If_File);
  88.       };
  89.    };
  90.  
  91.    # Delete $Path if necess.
  92.    if ($Type)
  93.    {
  94.       return (-1, $Type, "could not remove old $Type $Path") 
  95.          if (system ("/bin/rm -r $Path"));
  96.       $Msg = "removed $Type $Path";
  97.       return (0, $Type, $Msg);
  98.    };
  99.  
  100.    return (1, $Type, $Msg);
  101. };
  102.  
  103.  
  104. ;###############################################################################
  105. ;# Create_Symlink
  106. ;#
  107. ;# Creates a symbolic link from $Link_From -> $Link_To. Note that the link will
  108. ;# NOT be no matter what the Ovveride's are set to if it would result in a 
  109. ;# recursive link. May delete an old  $Link_To depending on the Override 
  110. ;# arguments.
  111. ;#
  112. ;# Arguments:
  113. ;#    $Link_To, $Link_From, $Override_If_Link, $Override_If_File,
  114. ;#    $Override_If_Dir
  115. ;#
  116. ;# Returns:
  117. ;#    $Status, $Msg
  118. ;###############################################################################
  119. sub Create_Symlink
  120. {
  121.    local ($Link_To, $Link_From, $Override_If_Link, $Override_If_File,
  122.           $Override_If_Dir) = @_;
  123.    local ($Remove, $Type, $Msg, $Link_From_Real, $Link_To_Real, 
  124.           $Link_From_Basename, $Link_From_Dir, $Real_Path, $Status);
  125.  
  126.    # Determine whether $Link_From and $Link_To point to the same object!
  127.    ($Link_From_Basename = $Link_From) =~ s/.*\///;
  128.    $Link_From_Dir = &Dir_Name ($Link_From);
  129.    return (0, $Real_Path) if (! (($Status, $Real_Path) = &Real_Path ($Link_From_Dir))[0]);
  130.    chop ($Real_Path) if ($Real_Path =~ /^(\/){1,2}$/);
  131.    $Link_From_Real = "$Real_Path/$Link_From_Basename";
  132.    $Link_To_Real = "$Link_From_Dir/$Link_To" if ($Link_To !~ /^\//);
  133.    return (0, $Link_To_Real) if (! (($Status, $Link_To_Real) = &Real_Path ($Link_To_Real))[0]);
  134.    return (0, "$Link_From -> $Link_To would be a recursive link") 
  135.       if ($Link_From_Real eq $Link_To_Real);
  136.  
  137.    # Possibly delete $Link_To
  138.    return (-1, $Msg) 
  139.       if ((($Status, $Type, $Msg) = &Maybee_Delete_Path ($Link_From, $Override_If_Link, $Override_If_File,
  140.                                                          $Override_If_Dir))[0] == -1);
  141.  
  142.    # Create the link!
  143.    $Msg .= ", " if ($Msg);
  144.    return (0, "${Msg}error creating link $Link_From -> $Link_To") 
  145.       if (! symlink ($Link_To, $Link_From));
  146.    return (1, "${Msg}created link $Link_From -> $Link_To");
  147. };
  148.  
  149.  
  150. ;###############################################################################
  151. ;# Create_Dir
  152. ;#
  153. ;# Creates a directory $Path. May delete an old $Path depending on the
  154. ;# Override arguments. Uses $Mode as the mode of the directory. $Mode had better
  155. ;# be in octal!!
  156. ;#
  157. ;# Arguments:
  158. ;#    $Path, $Mode, $Override_If_Link, $Override_If_File, $Override_If_Dir
  159. ;#
  160. ;# Returns:
  161. ;#    $Status, $Msg
  162. ;###############################################################################
  163. sub Create_Dir
  164. {
  165.    local ($Path, $Mode, $Override_If_Link, $Override_If_File, 
  166.           $Override_If_Dir) = @_;
  167.    local ($Status, $Msg);
  168.  
  169.    # Possibly delete $Link_To
  170.    return (-1, $Msg) 
  171.       if ((($Status, $Type, $Msg) = &Maybee_Delete_Path ($Path, $Override_If_Link, $Override_If_File,
  172.                                                          $Override_If_Dir))[0] == -1);
  173.  
  174.    # Convert a mode in form 0[0-9]{1,3} to cotal because it must be ASCII
  175.    $Mode = oct ($Mode) if ($Mode =~ /^0/);
  176.  
  177.    # Create the directory
  178.    $Msg .= ", " if ($Msg);
  179.    return (0, "${Msg}error directory $Path") 
  180.       if (! mkdir ($Path, $Mode));
  181.    return (1, "${Msg}created directory $Path");
  182. };
  183.  
  184. ;###############################################################################
  185. ;# Change_File_Info
  186. ;#
  187. ;# This function can change the owner, group, and modes of a file or directory.
  188. ;# It will only perform these operations if the function arguments are
  189. ;# not -1. As an example, the following will change the mode and group
  190. ;# of a file and leave the owner unchanged:
  191. ;#
  192. ;#    ($Status, $Msg) = &Change_FIle_Info ($File, 0555, -1, "staff", 1)
  193. ;#
  194. ;# By default this function requires numerical user and group IDs. However, if
  195. ;# $Lookup_IDs is 1 then the $Owner and $Group will be interpreted as
  196. ;# actual login names or group names.
  197. ;#
  198. ;# Returns with a $Status of 1 if everything went AOK; otherwise, $Status is
  199. ;# 0 and $Msg contains an error message.
  200. ;#
  201. ;# Arguments:
  202. ;#    $Path, $Mode, $Owner, $Group, $Lookup_IDs
  203. ;#
  204. ;# Returns:
  205. ;#    $Status, $Msg
  206. ;###############################################################################
  207. sub Change_File_Info
  208. {
  209.    local ($Path, $Mode, $Owner, $Group, $Lookup_IDs) = @_;
  210.    local ($Uid, $Gid);
  211.  
  212.    # Change owner and/or mode
  213.    if (($Owner != -1) || ($Group != -1))
  214.    {
  215.       # Get the default owner and group of the file
  216.       (($Uid, $Gid) = (stat ($Path))[4,5]) || return (0, "error stating $Path");
  217.  
  218.       # Override the default owner?
  219.       if ($Owner != -1)
  220.       {
  221.          if ($Lookup_IDs)
  222.          {
  223.             $Uid = (getpwnam ($Owner))[2];
  224.            return (0, "no such user: $Owner") if ($Uid eq "");
  225.          }
  226.      else
  227.          {
  228.             $Uid = $Owner;
  229.          };
  230.       };
  231.  
  232.       # Override the default group?
  233.       if ($Group != -1)
  234.       {
  235.          if ($Lookup_IDs)
  236.          {
  237.            $Gid = (getgrnam ($Group))[2];
  238.         return (0, "no such group: $Group") if ($Gid eq "");
  239.          }
  240.          else
  241.          {
  242.             $Gid = $Group;
  243.          };
  244.       };
  245.  
  246.       # Change owner/group
  247.       chown ($Uid, $Gid, $Path) || return (0, "error changing owner/group of $Path");
  248.    };
  249.  
  250.    # Change mode
  251.    if ($Mode != -1)
  252.    {
  253.       $Mode = oct ($Mode) if ($Mode =~ /^0/);
  254.       chmod ($Mode, $Path) || return (0, "error changing mode of $Path");
  255.    };
  256.  
  257.    return (1);
  258. };
  259.  
  260.  
  261. ;###############################################################################
  262. ;# Copy_File
  263. ;#
  264. ;# Copies $Source to $Dest. If $Mode, $Owner, or $Group are -1 their default
  265. ;# values are used. Their default will be computed via the umask, ACLs,
  266. ;# etc or, if $Preserve is 1, the mode, owner, and group of the original file
  267. ;# is maintained. When $Preserve $Mode, $Owner, or $Group are ignored as you
  268. ;# would expect.
  269. ;#
  270. ;# By default this function requires numerical user and group IDs. However, if
  271. ;# $Lookup_IDs is 1 then the $Owner and $Group will be interpreted as
  272. ;# actual login names or group names.
  273. ;#
  274. ;# If $Force is 1 any pre-existing destination file will be overriden even
  275. ;# if the file is read only.
  276. ;#
  277. ;# Returns with a $Status of 1 if everything went AOK; otherwise, $Status is
  278. ;# 0 and $Msg contains an error message.
  279. ;#
  280. ;# Arguments:
  281. ;#    $Source, $Dest, $Preserve, $Mode, $Owner, $Group, $Lookup_IDs,
  282. ;#    $Force
  283. ;#
  284. ;# Returns:
  285. ;#    $Status, $Msg
  286. ;###############################################################################
  287. sub Copy_File
  288. {
  289.    local ($Source, $Dest, $Preserve, $Mode, $Owner, $Group, $Lookup_IDs,
  290.       $Force) = @_;
  291.    local ($Output);
  292.  
  293.    # If the dest file exists and is not writable ...
  294.    # mode.
  295.    if ((-f $Dest) && (! -w $Dest))
  296.    {
  297.       # If not force mode copy will fail
  298.       return (0, "$Dest is not writable") if (! $Force);
  299.  
  300.       # Force mode, try to change the mode. We can only change its mode if 
  301.       # we own it
  302.       if ((stat (_))[4] == $>)
  303.       {
  304.          system ("chmod u+w $Dest") && return (0, "error making $Dest writable to owner");
  305.       }
  306.       else
  307.       {
  308.          return (0, "$Dest is not writable and you do not own it");
  309.       };
  310.    };
  311.  
  312.    # Copy
  313.    $Output = `/bin/sh -c 'cp $Source $Dest' 2>&1`;
  314.    $Output =~ s/\n$//;
  315.    return (0, $Output) if ($Output);
  316.  
  317.    # If we want to change the mode of the destination to match the source
  318.    # then we need to stat() it
  319.    if ($Preserve)
  320.    {
  321.       (($Mode, $Owner, $Group) = (stat ($Source))[2,4,5]) || return (0, "error stating $Source");
  322.       $Lookup_IDs = 0;
  323.    };
  324.  
  325.    # Change the uid, gid, or mode of the destination
  326.    return &Change_File_Info ($Dest, $Mode, $Owner, $Group, $Lookup_IDs);
  327. };
  328.  
  329.  
  330. 1;
  331.