Ejemplo n.º 1
0
import lind_test_server

from lind_fs_constants import *

lind_test_server._blank_fs_init()

# Let's add a few directories to the system and see if it works...
lind_test_server.mkdir_syscall('/bar',S_IRWXA)
lind_test_server.mkdir_syscall('/bar/baz',S_IRWXA)
lind_test_server.mkdir_syscall('/bar/bap',0)

# Create a new file...
fd = lind_test_server.open_syscall('/bar/bam',O_CREAT,0)
lind_test_server.close_syscall(fd)

# Read the root directory...
rootfd = lind_test_server.open_syscall('/',0,0)
val = lind_test_server.getdents_syscall(rootfd, 100)
assert (val==[(3, 'bar', DT_DIR, 24), (1, '..', DT_DIR, 24),\
  (1, '.', DT_DIR, 24)]), "Found: %s"%(str(val))

# Read the /bar directory...
barfd = lind_test_server.open_syscall('/bar',0,0)

# The buffer size is given small, only few entries are read. 
val = lind_test_server.getdents_syscall(barfd, 80)
assert (val == [(6, 'bam', DT_REG, 24), (4, 'baz', DT_DIR, 24),\
  (5, 'bap', DT_DIR, 24)]), "Found: %s"%(str(val))

# Again call on the same FD, should continue parsing the /bar directory.
val = lind_test_server.getdents_syscall(barfd, 80)
Ejemplo n.º 2
0
def generate_fs(syscalls, home_env=None):
  """
  <Purpose>
    This is the only public function of this module. It takes a list of
    Syscall objects as an argument and generates a Lind fs based on the
    information gathered from these system calls.

  <Arguments>
    syscalls:
      A list of Syscall objects, representing system calls parsed from a trace
      file.

    home_env:
      The HOME environment variable extracted from the traced execve sytem call.

  <Exceptions>
    None
  
  <Side Effects>
    Generates a set of files that make up the Lind file system.

  <Returns>
    None

  """

  # load an initial lind file system.
  lind_test_server._blank_fs_init()

  # Keep track of all the file paths dealt with and make a note of whether the
  # file was added to the lind fs or not. Example: {"filename.txt":True,
  # "filename2.txt":False} where True indicates the file was added into the lind
  # fs and False means the file was seen but wasn't added to the lind fs. We
  # keep track of all the paths met so far for two reasons. Firstly, we want to
  # construct the INITIAL file system state, so we only deal with the first
  # occurence of each path. For example consider the following sequence of 
  # traced system calls example:
  #
  #   11443 open("test.txt", O_RDONLY) = -1 ENOENT (No such file or directory)
  #     ...
  #   11443 open("test.txt", O_RDONLY) = 3
  #
  # In this example when the "test.txt" path is met for the first time, the file
  # does not exist (indicated by: -1 ENOENT). Subsequently, the "test.txt" path
  # is met again and in this case the file does exist. In this case we do NOT
  # want to include the "test.txt" file in the lind fs, because the initial file
  # system state did not include this file, even though the file is eventually
  # created.
  #
  # The second reason we keep track of all the paths met and whether they were 
  # added in the lind fs is to confirm whether the lind fs was constructed 
  # successfully.
  seen_paths = {}

  # a list of system calls that include a filepath in their arguments. We only
  # care about these system calls so only the actions representing of these
  # system calls will be examined.
  syscalls_with_path = ['open', 'creat', 'statfs', 'access', 'stat', 'link', 
                        'unlink', 'chdir', 'rmdir', 'mkdir']
  
  for action in actions:
    # the general format of an action is the following:
    # (syscall_name, (arguments tuple), (return tuple))
    # 
    # Example successful syscall action:
    # ('open_syscall', ('syscalls.txt', ['O_RDONLY', 'O_CREAT'], 
    #    ['S_IWUSR', 'S_IRUSR', 'S_IWGRP', 'S_IRGRP', 'S_IROTH']), 
    #            (3, None))
    #
    # Example unsuccessful syscall actions:
    # ('access_syscall', ('/etc/ld.so.nohwcap', ['F_OK']), 
    #                  (-1, 'ENOENT'))
    # ('mkdir_syscall', ('syscalls_dir', ['S_IRWXU', 'S_IRWXG', 
    #        'S_IXOTH', 'S_IROTH']), (-1, 'EEXIST'))
    syscall_name, syscall_parameters, syscall_result = action

    if DEBUG:
      print "Action:", action

    # each syscall name should end with _syscall
    if not syscall_name.endswith("_syscall"):
      raise Exception("Unexpected name of system call '" + 
                      syscall_name + "'")

    # remove the _syscall part from the syscall name
    syscall_name = syscall_name[:syscall_name.find("_syscall")]

    if syscall_name in syscalls_with_path:

      # TODO: I should consider O_CREAT O_EXECL and O_TRUNC flags.

      # check if the system call is open and whether it includes the O_CREAT
      # flag. If it does, set the o_creat flag to True, otherwise set it to
      # False. The o_creat flag will be used when trying to add a file, to
      # indicate how to handle the case the actual file is missing.
      # Specifically, when trying to add a file into the lind fs that does not
      # exist in the local fs, an exception will be raised, unless the o_creat
      # flag is set to True, in which case a warning will be printed instead.
      o_creat = False
      if syscall_name == "open":
        open_flags = action[1][1]
        if "O_CREAT" in open_flags:
          o_creat = True
      
      # Similarly, if the system call is creat, set the o_creat flag to True
      if syscall_name == "creat":
        o_creat = True

      # get the file path from the action
      path = action[1][0]

      # We want the initial file system state. So deal only with the earliest
      # syscall pertaining to a path.      
      if path not in seen_paths:
        # if the syscall was successful, copy file/dir into the lind fs.
        if syscall_result != (-1, 'ENOENT'):
          path, path_added = _copy_path_into_lind(path, home_path, o_creat)
          
          # remember this path was seen and whether it was added to the lind fs.
          seen_paths[path] = path_added
        
        else:
          # remember this path was seen but not added to the lind fs.
          seen_paths[path] = False

      # the link syscall contains a second path.
      if syscall_name == 'link':
        # ('link_syscall', ('syscalls.txt', 'syscalls.link'), (0, None))
        path2 = action[1][1]

        if path2 not in seen_paths:
          # if we got an exists error, the file must have been there
          # already, so we add it in the lind fs.
          if syscall_result == (-1, 'EEXIST'):
            path2, path_added = _copy_path_into_lind(path2, home_path, o_creat)
            
            # remember this path was seen and whether it was added to the lind fs.
            seen_paths[path2] = path_added
          
          else:
            # remember this path was seen but not added to the lind fs.
            seen_paths[path2] = False

      """
        TODO: Can add support for symlink here. Slightly more tricky due to 
        return part and error messages.
      """

      # change the home directory and the lind current directory so that future 
      # references to relative paths will be handled correctly.
      if syscall_name == 'chdir':
        home_path = os.path.join(home_path, path)
        home_path = os.path.normpath(home_path)
        lind_test_server.chdir_syscall(home_path)

      
  
  if DEBUG:
    print
    print "Seen Paths"
    print seen_paths

  # all actions are now read. Let's confirm that lind fs is as expected.
  all_lind_paths = list_all_lind_paths()

  if DEBUG:
    print
    print "Lind Paths"
    print all_lind_paths

  for seen_path in seen_paths:
    # convert to lind absolute path.
    abs_seen_path = seen_path
    if not abs_seen_path.startswith("/"):
      abs_seen_path = "/" + abs_seen_path

    abs_seen_path = os.path.normpath(abs_seen_path)

    # skip the root
    if abs_seen_path == "/":
      continue

    if seen_paths[seen_path]:
      # the file should be in lind fs.
      if abs_seen_path not in all_lind_paths:
        raise Exception("Expected file '" + abs_seen_path + 
                        "' not found in Lind fs")
    else:
      # file should not be in lind fs.
      if abs_seen_path in all_lind_paths:
        raise Exception("Unexpected file '" + abs_seen_path + "' in Lind fs")
Ejemplo n.º 3
0
def main():
  # I can be imported as a module too!!!
  if len(sys.argv)==1:
    print_usage()
    return

  command = sys.argv[1]
  args = sys.argv[2:]



#help                       : print this message
#usage                      : print this message
  if command == 'help' or command == 'usage':
    print_usage()



#cp root file1 [file2...]   : copies files from the root into the lindfs.   For
#                             example, cp bar /etc/passwd /bin/ls will copy
#                             bar/etc/passwd, bar/bin/ls as /etc/passwd, /bin/ls
  elif command == 'cp':
    lind_test_server.load_fs()

    if len(args)<2:
      print 'Too few arguments to cp.   Must specify root and at least one file'
      return

    root = args[0]
    for filetocp in args[1:]:
      cp_into_lind(filetocp, rootpath=root)



#find [startingpath]        : print the names of all files / paths in the fs
#                             This is much like 'find /'
  elif command == 'find':
    lind_test_server.load_fs()

    if len(args)>1:
      print 'Too many arguments to find.   Takes an optional path'
      return
    elif len(args) == 0:
      startingpath = '/'
    elif len(args)==1:
      startingpath = args[0]
      
    allpathlist = list_all_lind_paths(startingdir=startingpath)
    # want to print this more cleanly than as a list
    for thispath in allpathlist:
      print thispath


#format                     : make a new blank fs, removing the current one.
  elif command == 'format':
    lind_test_server._blank_fs_init()


#deltree dirname            : delete a directory and all it contains
  elif command == 'deltree':
    lind_test_server.load_fs()

    if len(args)!= 1:
      print 'deltree takes exactly one argument, the dir to remove'
      return

    print 'Unimplemented...'

#rm file1 [file2...]        : delete a file
  elif command == 'rm':
    lind_test_server.load_fs()

    if len(args) == 0:
      print 'rm takes one or more arguments'
      return

    for filename in args:
      lind_test_server.unlink_syscall(filename)



#mkdir dir1 [dir2...]       : create a directory
  elif command == 'mkdir':
    lind_test_server.load_fs()

    if len(args) == 0:
      print 'mkdir takes one or more arguments'
      return

    for dirname in args:
      lind_test_server.mkdir_syscall(dirname,S_IRWXA)



#rmdir dir1 [dir2...]       : delete a directory
  elif command == 'rmdir':
    lind_test_server.load_fs()

    if len(args) == 0:
      print 'rmdir takes one or more arguments'
      return

    for dirname in args:
      lind_test_server.rmdir_syscall(dirname)


# OTHERWISE?
  else:
    print "ERROR: command unknown"
    print
    print_usage()
    return
Ejemplo n.º 4
0
def main():
  # I can be imported as a module too!!!
  if len(sys.argv)==1:
    print_usage()
    return

  command = sys.argv[1]
  args = sys.argv[2:]



#help                       : print this message
#usage                      : print this message
  if command == 'help' or command == 'usage':
    print_usage()



#cp root file1 [file2...]   : copies files from the root into the lindfs.   For
#                             example, cp bar /etc/passwd /bin/ls will copy
#                             bar/etc/passwd, bar/bin/ls as /etc/passwd, /bin/ls
  elif command == 'cp':
    lind_test_server.load_fs()

    if len(args)<2:
      print 'Too few arguments to cp.   Must specify root and at least one file'
      return

    root = args[0]
    for filetocp in args[1:]:
      cp_dir_into_lind(filetocp, rootpath=root)

#update root file1 [file2...]   : copies files from the root into the lindfs if they are different.   For
#                                 example, cp bar /etc/passwd /bin/ls will copy
#                                 bar/etc/passwd, bar/bin/ls as /etc/passwd, /bin/ls
  elif command == 'update':
    lind_test_server.load_fs()

    if len(args)<2:
      print 'Too few arguments to update.   Must specify root and at least one file'
      return

    root = args[0]
    for filetoup in args[1:]:
      update_dir_into_lind(filetoup, rootpath=root)


#find [startingpath]        : print the names of all files / paths in the fs
#                             This is much like 'find /'
  elif command == 'find':
    lind_test_server.load_fs()

    if len(args)>1:
      print 'Too many arguments to find.   Takes an optional path'
      return
    elif len(args) == 0:
      startingpath = '/'
    elif len(args)==1:
      startingpath = args[0]
      
    allpathlist = list_all_lind_paths(startingdir=startingpath)
    # want to print this more cleanly than as a list
    #for thispath in allpathlist:
    #  print thispath


#format                     : make a new blank fs, removing the current one.
  elif command == 'format':
    lind_test_server._blank_fs_init()


#deltree dirname            : delete a directory and all it contains
  elif command == 'deltree':
    lind_test_server.load_fs()

    if len(args)!= 1:
      print 'deltree takes exactly one argument, the dir to remove'
      return
 
    deltree_lind(args[0])

#rm file1 [file2...]        : delete a file
  elif command == 'rm':
    lind_test_server.load_fs()

    if len(args) == 0:
      print 'rm takes one or more arguments'
      return

    for filename in args:
      lind_test_server.unlink_syscall(filename)



#mkdir dir1 [dir2...]       : create a directory
  elif command == 'mkdir':
    lind_test_server.load_fs()

    if len(args) == 0:
      print 'mkdir takes one or more arguments'
      return

    for dirname in args:
      lind_test_server.mkdir_syscall(dirname,S_IRWXA)



#rmdir dir1 [dir2...]       : delete a directory
  elif command == 'rmdir':
    lind_test_server.load_fs()

    if len(args) == 0:
      print 'rmdir takes one or more arguments'
      return

    for dirname in args:
      lind_test_server.rmdir_syscall(dirname)


# OTHERWISE?
  else:
    print "ERROR: command unknown"
    print
    print_usage()
    return
Ejemplo n.º 5
0
def generate_fs(actions, trace_path):
    # Relative paths found in actions are related to this HOME_PATH. It is initially
    # set to an empty string which ultimately translates to the current directory.
    home_path = ''

    # read the trace and examine the execve syscall to see if the HOME environment
    # variable is set to somewhere else. This usually happens when running
    # benchmarks. The reason to do this is because actions referring to files
    # using relative paths, might refere to these files relative to the HOME
    # variable defined in the execve syscall.
    fh = open(trace_path, "r")
    # the execve syscall is the first action of the trace file
    execve_line = fh.readline()
    fh.close()

    # If the 'HOME' variable is defined in the execve line, the HOME_PATH
    # variable will be set to the path of 'HOME'.
    if execve_line.find("execve(") != -1:
        execve_parts = execve_line.split(", ")
        # the parameter of the HOME variable in the execve syscall has this format:
        # "HOME=/home/savvas/tests/" including the double quotes.
        for part in execve_parts:
            if part.startswith("\"HOME="):
                part = part.strip("\"")
                assert (part.startswith("HOME="))
                home_path = part[part.find("HOME=") + 5:]

    # load an initial lind file system.
    lind_test_server._blank_fs_init()

    # Keep track of all the file paths dealt with and make a note of whether the
    # file was added to the lind fs or not. Example: {"filename.txt":True,
    # "filename2.txt":False} where True indicates the file was added into the lind
    # fs and False means the file was seen but wasn't added to the lind fs. We
    # keep track of all the paths met so far for two reasons. Firstly, we want to
    # construct the INITIAL file system state, so we only deal with the first
    # occurence of each path. For example consider the following sequence of
    # traced system calls example:
    #
    #   11443 open("test.txt", O_RDONLY) = -1 ENOENT (No such file or directory)
    #     ...
    #   11443 open("test.txt", O_RDONLY) = 3
    #
    # In this example when the "test.txt" path is met for the first time, the file
    # does not exist (indicated by: -1 ENOENT). Subsequently, the "test.txt" path
    # is met again and in this case the file does exist. In this case we do NOT
    # want to include the "test.txt" file in the lind fs, because the initial file
    # system state did not include this file, even though the file is eventually
    # created.
    #
    # The second reason we keep track of all the paths met and whether they were
    # added in the lind fs is to confirm whether the lind fs was constructed
    # successfully.
    seen_paths = {}

    # a list of system calls that include a filepath in their arguments. We only
    # care about these system calls so only the actions representing of these
    # system calls will be examined.
    syscalls_with_path = [
        'open', 'creat', 'statfs', 'access', 'stat', 'link', 'unlink', 'chdir',
        'rmdir', 'mkdir'
    ]

    for action in actions:
        # the general format of an action is the following:
        # (syscall_name, (arguments tuple), (return tuple))
        #
        # Example successful syscall action:
        # ('open_syscall', ('syscalls.txt', ['O_RDONLY', 'O_CREAT'],
        #    ['S_IWUSR', 'S_IRUSR', 'S_IWGRP', 'S_IRGRP', 'S_IROTH']),
        #            (3, None))
        #
        # Example unsuccessful syscall actions:
        # ('access_syscall', ('/etc/ld.so.nohwcap', ['F_OK']),
        #                  (-1, 'ENOENT'))
        # ('mkdir_syscall', ('syscalls_dir', ['S_IRWXU', 'S_IRWXG',
        #        'S_IXOTH', 'S_IROTH']), (-1, 'EEXIST'))
        syscall_name, syscall_parameters, syscall_result = action

        if DEBUG:
            print "Action:", action

        # each syscall name should end with _syscall
        if not syscall_name.endswith("_syscall"):
            raise Exception("Unexpected name of system call '" + syscall_name +
                            "'")

        # remove the _syscall part from the syscall name
        syscall_name = syscall_name[:syscall_name.find("_syscall")]

        if syscall_name in syscalls_with_path:

            # TODO: I should consider O_CREAT O_EXECL and O_TRUNC flags.

            # check if the system call is open and whether it includes the O_CREAT
            # flag. If it does, set the o_creat flag to True, otherwise set it to
            # False. The o_creat flag will be used when trying to add a file, to
            # indicate how to handle the case the actual file is missing.
            # Specifically, when trying to add a file into the lind fs that does not
            # exist in the local fs, an exception will be raised, unless the o_creat
            # flag is set to True, in which case a warning will be printed instead.
            o_creat = False
            if syscall_name == "open":
                open_flags = action[1][1]
                if "O_CREAT" in open_flags:
                    o_creat = True

            # Similarly, if the system call is creat, set the o_creat flag to True
            if syscall_name == "creat":
                o_creat = True

            # get the file path from the action
            path = action[1][0]

            # We want the initial file system state. So deal only with the earliest
            # syscall pertaining to a path.
            if path not in seen_paths:
                # if the syscall was successful, copy file/dir into the lind fs.
                if syscall_result != (-1, 'ENOENT'):
                    path, path_added = _copy_path_into_lind(
                        path, home_path, o_creat)

                    # remember this path was seen and whether it was added to the lind fs.
                    seen_paths[path] = path_added

                else:
                    # remember this path was seen but not added to the lind fs.
                    seen_paths[path] = False

            # the link syscall contains a second path.
            if syscall_name == 'link':
                # ('link_syscall', ('syscalls.txt', 'syscalls.link'), (0, None))
                path2 = action[1][1]

                if path2 not in seen_paths:
                    # if we got an exists error, the file must have been there
                    # already, so we add it in the lind fs.
                    if syscall_result == (-1, 'EEXIST'):
                        path2, path_added = _copy_path_into_lind(
                            path2, home_path, o_creat)

                        # remember this path was seen and whether it was added to the lind fs.
                        seen_paths[path2] = path_added

                    else:
                        # remember this path was seen but not added to the lind fs.
                        seen_paths[path2] = False
            """
        TODO: Can add support for symlink here. Slightly more tricky due to 
        return part and error messages.
      """

            # change the home directory and the lind current directory so that future
            # references to relative paths will be handled correctly.
            if syscall_name == 'chdir':
                home_path = os.path.join(home_path, path)
                home_path = os.path.normpath(home_path)
                lind_test_server.chdir_syscall(home_path)

    if DEBUG:
        print
        print "Seen Paths"
        print seen_paths

    # all actions are now read. Let's confirm that lind fs is as expected.
    all_lind_paths = list_all_lind_paths()

    if DEBUG:
        print
        print "Lind Paths"
        print all_lind_paths

    for seen_path in seen_paths:
        # convert to lind absolute path.
        abs_seen_path = seen_path
        if not abs_seen_path.startswith("/"):
            abs_seen_path = "/" + abs_seen_path

        abs_seen_path = os.path.normpath(abs_seen_path)

        # skip the root
        if abs_seen_path == "/":
            continue

        if seen_paths[seen_path]:
            # the file should be in lind fs.
            if abs_seen_path not in all_lind_paths:
                raise Exception("Expected file '" + abs_seen_path +
                                "' not found in Lind fs")
        else:
            # file should not be in lind fs.
            if abs_seen_path in all_lind_paths:
                raise Exception("Unexpected file '" + abs_seen_path +
                                "' in Lind fs")
Ejemplo n.º 6
0
def wipe_cmd():
	"""wipe this file system"""
	cd_cmd("/") # cd so we dont get stuck in a non existant file post wipe!
	lind_test_server._blank_fs_init()
	print "Filesystem wiped"