Class: RStyx::Server::SDirectory

Inherits:
SFile
  • Object
show all
Defined in:
lib/rstyx/server.rb

Overview

Class representing a directory on the Styx server.

Direct Known Subclasses

DirectoryOnDisk

Instance Attribute Summary

Attributes inherited from SFile

#atime, #gid, #mtime, #muid, #name, #parent, #permissions, #uid, #version

Instance Method Summary collapse

Methods inherited from SFile

#add_changelistener, #add_client, #appendonly?, #auth?, #can_setlength?, #can_setmode?, #can_setmtime?, #can_setname?, #client, #client_connected, #client_disconnected, #contents_changed, #delete, #directory?, #exclusive?, #filetype, #full_path, #length, #length=, #mode, #mode=, #num_clients, #qid, #refresh, #remove, #remove_client, #remove_dead_clients, #rename, #reply_read, #reply_write, #set_mtime, #stat, #uuid, #version_incr, #write

Constructor Details

#initialize(name, argv = { :permissions => 0777, :uid => ENV["USER"], :gid => ENV["GROUP"], :filemaker => nil }) ⇒ SDirectory

Create a new directory with name name. Permissions are obtained from the argv hash as with SFile. The default permissions are 0777 though. In addition to the usual file arguments in argv, SDirectory instances also recognize a :filemaker key which specifies a block that may be called whenever a file is created. The block receives as parameters the SDirectory instance, the name of the file to create, and the permissions of the file. It should return an SFile subclass instance, which becomes the new file on success, or raise a StyxException if there is some problem.



1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
# File 'lib/rstyx/server.rb', line 1692

def initialize(name, argv={ :permissions => 0777, :uid => ENV["USER"],
                 :gid => ENV["GROUP"], :filemaker => nil })
  # directories cannot be append-only, exclusive, or auth files
  argv.merge({:apponly => false, :excl => false})
  super(name, argv)
  @directory = true
  @children = []
  @children.extend(MonitorMixin)
  @filemaker = argv[:filemaker]
end

Instance Method Details

#<<(child) ⇒ Object

Add an SFile child to this directory. If a file with the same name already exists, throws a FileExists exception.



1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
# File 'lib/rstyx/server.rb', line 1718

def <<(child)
  @children.synchronize do
    if child_exists?(child.name)
      raise FileExists("#{sf.name} already exists")
    end
    child.parent = self
    @children << child
  end
  return(child)
end

#[](name) ⇒ Object

Get the child with the name name, or nil if no such file is present in this directory.



1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
# File 'lib/rstyx/server.rb', line 1733

def [](name)
  if name == "."
    return(self)
  end
  if name == ".."
    return(self.parent)
  end
  @children.synchronize do
    @children.each do |c|
      if c.name == name
        return(c)
      end
    end
    return(nil)
  end
end

#child_countObject

Get the number of children this directory has



1753
1754
1755
# File 'lib/rstyx/server.rb', line 1753

def child_count
  return(@children.length)
end

#child_exists?(name) ⇒ Boolean

Returns:

  • (Boolean)


1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
# File 'lib/rstyx/server.rb', line 1703

def child_exists?(name)
  @children.synchronize do
    @children.each do |c|
      if c.name == name
        return(true)
      end
    end
    return(false)
  end
end

#newfile(name, perm, isdir, isapponly, isexcl) ⇒ Object

Create a new file with name name and permissions perm in this directory. – FIXME: make this method actually DO something! ++

Raises:



1808
1809
1810
# File 'lib/rstyx/server.rb', line 1808

def newfile(name, perm, isdir, isapponly, isexcl)
  raise StyxException.new("cannot create files in this directory")
end

#read(client, offset, count) ⇒ Object

Read the contents of the directory.

client

the SFileClient object representing the client reading from this directory.

offset

the offset the client wants to read from. Nonzero offsets are only valid if the client has read from the directory before, and may only be the values obtained from a previous read.

count

the number of bytes that the client wishes to read. The read will always return the nearest integral number of directory entries whose length is less than the count (i.e. if five entries take 300 bytes and the sixth entry takes 40 bytes, and count was set to 320, only five entries and 300 bytes will be returned).



1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
# File 'lib/rstyx/server.rb', line 1774

def read(client, offset, count)
  # Check that the offset is valid; zero offsets are always valid,
  # but non-zero offsets are only valid if this client has read part
  # of the contents of the directory before.
  if (offset != 0 && offset != client.offset)
    raise StyxException.new("invalid offset when reading directory")
  end

  # Create a string to store the serialized stat representations
  # of the directory's contents.
  str = ""
  nextfile = (offset == 0) ? 0 : client.next_file_to_read
  while (nextfile < @children.length)
    sf = @children[nextfile]
    s = sf.stat.to_bytes
    if (s.length + str.length) > count
      break
    end
    # Add the serialized stat to the buffer
    str << s
    nextfile += 1
  end
  client.next_file_to_read = nextfile
  client.offset += str.length
  return(reply_read(str))
end

#remove_child(child) ⇒ Object

Remove a file from the directory



1814
1815
1816
1817
# File 'lib/rstyx/server.rb', line 1814

def remove_child(child)
  @children.delete(child)
  self.contents_changed
end