LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   A gawk program to mount all ISO images in a directory under a specified mount-point (https://www.linuxquestions.org/questions/programming-9/a-gawk-program-to-mount-all-iso-images-in-a-directory-under-a-specified-mount-point-842464/)

PTrenholme 11-04-2010 10:04 PM

A gawk program to mount all ISO images in a directory under a specified mount-point
 
Not a question, but I thought the use of the gawk "pipe" extension to process system commands might be interesting to others.

The problem: I'd downloaded several ISO images of the Baen Books CDs that they sometimes make available with their hard-cover books. (The CDs contain unencrypted copyrighted SF and fantasy books - several hundred of them - and non-commercial copying and distribution is permitted. Google "Baen CD" for sites distributing the images.)

I tried to write this in bash, but I wanted the directory names to be the same as the CD names, and those names contain blanks and single quotes and other "special" characters, so the bash code was somewhat complicated. :)

So, here's the code I wrote (with default source and destination locations which could, I hope, be overwritten with command-line arguments if the gawk code is invoked as a command.

Here's the code:
Code:

$ cat Scripts/gawk/mount_iso_images
#!/bin/gawk -f
#
# Usage: ./mount_iso_images {source_directory {mount_base}}
#
BEGIN {
#
# Set this to a non-zero value for some debugging output
  debug=0
# See "man console_codes" for code descriptions.
  csi="\x1B["
  red= csi "31m"
  reset= csi "39m"
# Set defaults if necessary
  loc=ARGV[1]
  if (loc == "") loc="/Backups/Downloads/Other/CD Images"
  if (debug) print "loc=" loc
# Note the added quote prefix.
  root_base="\"" ARGV[2]
  if (root_base == "\"") root_base="\"/mnt/ISO/"
  if (debug) print "root_base=" root_base
 # Get the program name for use in error messages, if any.
  exe=ARGV[0]
  if (exe == "") {
    exe="mount_iso_images"
  }
  else {
    cmd = "basename " exe
    cmd | getline exe
    close(cmd)
  }
  if (debug) print "exe=" exe
# Get the list of ISO files to be mounted into a temporary file
  tmp_dir="/tmp/mount-" ENVIRON["LOGNAME"]
  cmd="mkdir -p " tmp_dir
  if (system(cmd)) {
    print red exe ": Failed to create " tmp_dir reset > "/dev/stderr"
    exit(1)
  }
  if (debug) print "temp_dir=" tmp_dir
  temp=tmp_dir "/iso_list"
  cmd="touch " temp
  if (system(cmd)) {
    print red exe ": Unable to create the temporary file " temp reset > "/dev/stderr"
    exit(2)
  }
  if (debug) print "temp=" temp
  list="ls -1 \"" loc "\" > " temp
  if (system(list)) {
    print red exe ": system(" list ") call failed." reset > "/dev/stderr"
    exit(3)
  }
  printf("This program requires root access.\nEnter your ")
  if (system("sudo echo O.K.")) {
    exit(4)
  }
# How many loop devices are defined?
  cmd="ls /dev/loop* | wc -w"
  cmd | getline max_loops
# Don't try to mount more images then there are available loop devices . . .
  loops_used=0
# Read the list of entries in the source directory from the temp file.
  while ((getline < temp) && (loops_used < max_loops)) {
# Clear any prior values
    name = root = path = ""
# Get the file name
    cmd="basename \"" $0 "\""
    cmd | getline name
    close(cmd)
    if (name=="") {
      print red exe ": Failed to find the base name of \"" f ".\"" reset > "/dev/stderr"
      continue
    }
# Build the mount name. Note the added terminal quote.
    root= root_base gensub(/\.iso$/,"","no",name) "\""
    path="\"" loc "/" name "\""
    cmd="file " path
    cmd | getline test
    if (test !~ /ISO 9660/) {
# In case the "mount..." and "umount..." commands are in the ISO file directory, don't report skipping them.
      if (debug && (path !~ "u*" exe )) print red exe ": " path " is not a iso9660 image. Skipped." reset > "/dev/stderr"
      continue
    }
# Put the "name" in quotes
    name= "\"" name "\""
    if (system("sudo mkdir -p " root)) {
      print red exe ": Failed to create directory " root reset > "/dev/stderr"
      continue
    }
    if (system("sudo mount -t iso9660 -o loop,ro,defaults " path " " root) == 0) {
      print exe ": " path " has been mounted on " root "."
      ++loops_used
    }
    else {
      print red exe ": Failed to mount " path "." reset > "/dev/stderr"
      system("sudo rmdir " root)
    }
  }
# All done. Remove the temporary file.
  if (system("rm -rf " tmp_dir)) {
    print red exe ": Failed to remove " tmp_dir reset > "/dev/stderr"
  }
}

And here's the output from one run:
Code:

$ Scripts/gawk/mount_iso_images
This program requires root access.
Enter your [sudo] password for Peter:
O.K.
"/Backups/Downloads/Other/CD Images/Ghost.iso" has been mounted on "/mnt/ISO/Ghost".
"/Backups/Downloads/Other/CD Images/Mission of Honor.iso" has been mounted on "/mnt/ISO/Mission of Honor".
"/Backups/Downloads/Other/CD Images/The Claws that Catch.iso" has been mounted on "/mnt/ISO/The Claws that Catch".
"/Backups/Downloads/Other/CD Images/The Far Side of the Stars.iso" has been mounted on "/mnt/ISO/The Far Side of the Stars".
"/Backups/Downloads/Other/CD Images/This Scepter'd Isle.iso" has been mounted on "/mnt/ISO/This Scepter'd Isle".

Oh, here;s a simple bash script to clean up the mount points.
Code:

$ cat Scripts/bash/umount_iso_images
#!/bin/bash
echo This progran need root access.
sudo echo O.K.
loc="/Backups/Downloads/Other/CD Images"
[ $# -gt 0 ] && loc="$1"
if [ -d "${loc}" ]
then
  sudo umount /mnt/ISO/*
  sudo rmdir /mnt/ISO/*
else
  echo Not yet implimented.
fi

Comments and suggestions for improvement welcomed.

GrapefruiTgirl 11-09-2010 06:54 PM

Hi PTrenholm,

I think this is great!

Not something I'd probably use any time soon, but I really like to examine the code in programs like this, just to see exactly what you did and how you did it, and to take ideas from it about doing bashy sorts of things, with not bash. This sort of falls into the category of "do it because you can" or "to see if you can", and I find is a fun way to get better with awk, sed, or whatever tool(s) it happens to be. Plus, (I find) some syntaxes & concepts, you simply can't wrap your head around by reading man pages- you actually got to use it to figure it out.

All I can suggest (or ask actually) would be that you consider swapping out the PHP tags for regular code tags, as the PHP tags are terribly hard on the eyes, and they seem to cause weird sideways-scrolling issues with the webpage. :/ :)

If you're interested in looking at some more awk stuff that are more than the usual one-liners, I wrote a few lately too. I wanted to use some pipes, some arrays, some system() commands, and some getline's, just to learn their usage & syntax. For example, this here just parses a log file, but I went crazy around how arguments/parameters were passed to the program and parsed, and on prettying up the program output. This other thing is an awk program which feeds Dzen2 statusbars on my screens (date/time, CPU, RAM, disks etc..). Rationale was: I thought using awk would reduce the CPU load/time consumed by it, since it runs in a loop all the time I'm logged into the desktop. It used to be written in bash.

Anyhow, enough of my trying to steal your stage - thanks for posting your code! I'm sure someone will find it useful and/or educational.

Best regards.

PTrenholme 11-10-2010 01:13 PM

Celine, thanks for the feedback. :) Per your suggestion, I changed the tags. (On my system, the php tags give a nice color-coded display which makes it somewhat easier to follow, but simple code tags work, and I didn't realize that they presented a problem for other systems. Sorry.)

As you probably know, as soon as you post some code, you see a problems and awkwardness that you like to fix. So, here's my "improved" 0.2 version of the code:
Code:

#!/bin/gawk -f
BEGIN {
# Put the name of this program in the exe variable
  exe="mount_iso_files"
# Set to "true" for debugging output, "" for none.
  debug=""
# Print the help information if requested
  if (ARGV[1] ~ "-h" ) {
    printf(\
      exe ": Mount all iso9660 files in a directory, each as a seperate directory under the mount_point\n\n"\
      "Usage: " exe " {iso_directory {mount_point}}\n"\
      "\twhere\tiso_directory defaults to \"/ISO\"\n"\
      "\tand\tmount_point defaults to \"/mnt/ISO\"\n\n")
    exit(0)
  }
# See man console_codes for terminal display code descripions.
  csi    ="\x1B[0;"
  red    = csi "1;31m"
  blue        = csi "34m"
  white        = csi "37m"
  reset  = csi "39m"
# Make sure that we have root access (and check for running as root).
  cmd = "groups | grep -w root"
  cmd | getline in_root
  close(cmd)
  if (in_root == "") {
    printf("%s: This program requires root access.\n", exe)
    if (system("sudo echo O.K.")) {
      print red exe ": Terminating. Invalid access attempt." reset > "/dev/stderr"
      exit(255)
    }
  }
# Set defaults if necessary
  loc=ARGV[1]
  if (loc == "") loc="/ISO"
  if (debug) print blue exe " (debug): loc=" loc reset
  mount_point=ARG[2]
  if (mount_point == "") mount_point = "/mnt/ISO/"
  if (debug) print blue exe " (debug): mount_point=" mount_point reset
# Remove any mounted iso9660 files
  clean_exit(-1)
# Get the list of ISO files to be mounted into a temoprary file
  tmp_dir="/tmp/mount-" ENVIRON["LOGNAME"]
  cmd="mkdir -p " tmp_dir
  if (system(cmd)) {
    print red exe ": Failed to create " tmp_dir reset > "/dev/stderr"
    clean_exit(1)
  }
  if (debug) print blue exe " (debug): temp_dir=" tmp_dir reset
# Build the list of entries in the source directory
  temp=tmp_dir "/iso_list"
  cmd="touch " temp
  if (system(cmd)) {
    print red exe ": Unable to create the temporary file " temp reset > "/dev/stderr"
    clean_exit(2)
  }
  if (debug) print blue exe " (debug): temp=" temp reset
  list="ls -1 " loc " > " temp
  if (system(list)) {
    print red exe ": system(" list ") call failed." reset > "/dev/stderr"
    clean_exit(3)
  }
  if (debug) {
    print blue exe ": After executing \"" list ", " temp " contains:"
    system("cat " temp)
    print reset
  }
# Get the number of defined loop devices
  cmd="ls /dev/loop* | wc -w"
  cmd | getline max_loops
  close(cmd)
# Get the number of loop devices currently mounted
  cmd="grep -w loop= /etc/mtab | wc -l"
  cmd | getline loops_used
  close(cmd)
# Abort if we can't mount any more images
  if (loops_used >= max_loops) {
    print red exe ": All available loop devices (" max_loops " of them) are in use." reset
    exit(0)
  }
# Mount as many of the iso9660 images as possible
  while ((getline < temp) && (loops_used < max_loops)) {
# Make sure that he work variables used in the loop are cleared
# ToDo: automate this by moving the loop contents to a function
    name = root = path = test = test2 = ""
# Find the current entry's name
    cmd="basename \"" $0 "\""
    cmd | getline name
    close(cmd)
    if (name=="") {
      print red exe ": Failed to find the basename of \"" f ".\"" reset > "/dev/stderr"
      continue
    }
# Where should this entry be mounted?
    root=mount_point "\"" gensub(/\.iso$/,"","no",name) "\""
# Is the entry a iso9660 imaage?
    path= loc "/\"" name "\""
    cmd="file " path
    cmd | getline test
    close(cmd)
    if (test !~ /ISO 9660/) {
      if (debug && (path !~ "u*" exe )) print blue exe " (debug): " path " is not a iso9660 image. Skipped." reset > "/dev/stderr"
      continue
    }
# Is it already mounted? (Look at /etc/mtab to see why we're replacing blanks by backslashes.)
    cmd = "grep " gensub(/ /,"\\\\\\\\\\\\","g",root) " /etc/mtab"
    cmd | getline test2
    close(cmd)
    if (test2 != "") {
      if (debug) print blue exe " (debug): cmd=" cmd ", test2=\"" test2 "\""
      if (debug) print blue exe " (debug): " root " is already mounted. Skipping." reset
      continue
    }
# Create the mount point
    if (system("sudo mkdir -p " root)) {
      print red exe ": Failed to create directory " root reset > "/dev/stderr"
      continue
    }
# Mount the file system. (Error messages from the mount to be displayed in red.)
    printf("%s", red)
    if (system("sudo mount -t iso9660 -o loop,ro,defaults " path " " root) == 0) {
      print reset exe ": " path " has been mounted on " root "."
      ++loops_used
    }
    else {
# Remove the mount point if the mount failed. (If the mpunt point is in use, this will fail.)
      system("sudo rmdir " root)
      printf("%s",reset)
    }
  }
# All done.
  clean_exit(0)
}
function clean_exit(code) {
# No exit - just preliminary clean up.
  if (code < 0) {
# Unmount anything mounted under mount_point`
    printf("%s",red)
    if (system("sudo umount " mount_point "*")) {
      print exe ": Failed to umount " mount_point "*" reset > "/dev/stderr"
      printf("%s",reset)
      return
    }
# Remove any subdirectories under the mount_point
    if (system("sudo rmdir " mount_point "*")) {
      print red exe ": Failed to remove " mount_point " subdirectories." reset > "/dev/stderr"
      printf("%s",reset)
      return
    }
    printf("%s",reset)
    return
  }
# If here, error or normal exit. Delete the temoprary file and directory.
  else {
    printf("%s",red)
    if (system("[ -e " tmp_dir " ] && rm -rf " tmp_dir)) {
      print exe ": Failed to remove " tmp_dir > "/dev/stderr"
    }
    printf("%s",reset)
  }
  exit(code)
}

Fedora 14 only provides eight loopback devices in their default configuration. Do you have any idea how that could be increased? (I suspect that it's an option set when the kernel is compiled, but it might be a load-time parameter that could be changed.)

GrapefruiTgirl 11-10-2010 01:18 PM

Of course :) every time I post some code to share, I end up updating it many times :D so the version numbers are always creeping up. As for the loopback limit, it is indeed a kernel compile option, however:

You may find this interesting, from /your/kernel/sources/Documentation/kernel_parameters.txt:
Code:

        max_loop=      [LOOP] Maximum number of loopback devices that can
                        be mounted
                        Format: <1-256>

Best regards!

PTrenholme 11-13-2010 08:30 AM

Celine, adding max_loop=16 to the GRUB kernel=line bumped the number of loop devices from 8 to 16. Thanks for the hint. (I added that as a comment to your "reputation," but I don't know if you see those comments.)

grail 11-15-2010 07:56 AM

Nice work with the code and I too found it interesting. A personal point would be perhaps to incorporate a function or two for things that you repeat many times, ie like the
testing and printing of error messages:
Code:

  if (system(cmd)) {
    print red exe ": Failed to create " tmp_dir reset > "/dev/stderr"
    clean_exit(1)
  }

#or

  if (loc == "") loc="/ISO"
  if (debug) print blue exe " (debug): loc=" loc reset

I normally give myself a 3 times rule, ie if I write almost identical code 3 or more times then it is time for a function.
Like I said it is just a personal one :)

Good luck with the next revision :) (hard to stop at just one :) )

PTrenholme 11-15-2010 08:22 PM

Thanks grail :) that was a good suggestion, so here's version 1.0. designed to be run at the end of the boot process from /etc/rc.d/rc.local. (That's where Fedora keep the rc.local script. Other distributions use different locations. For example, Ubuntu uses /etc/rc.local.)

Code:

#!/bin/gawk -f
# Note: This script is intended to be run from rc.local (q.v.)
BEGIN {
# Put the name of this program in the exe variable
  if (exe=="") exe="rc.mount_iso_images.gawk"
# Make sure we're running as "root"
  in_root=cmd_result("groups | grep -w root")
  if (in_root == "") {
    printf("%s: This program requires root access.\n", exe)
    exit(255)
  }
# See man console_codes for terminal display code descriptions.
  csi    ="\x1B[0;"
  red    = csi "1;31m"
  blue        = csi "34m"
  white        = csi "37m"
  reset  = csi "39m"
# Set defaults if necessary
  if (loc == "") loc="/ISO"
  if (mount_point == "") mount_point = "/mnt/ISO/"
# Print the header
  print ""
  print "Mounting as many ISO 9660 images in " loc " under " mount_point " as possible."
  print ""
# Remove any mounted type iso9660 files and any subdirectories of "mount_point"
  if (run_cmd("umount -a -t iso9660", "umount -a -t iso9660 failed.", 0)) exit(254)
# Remove any subdirectories under the mount_point
  run_cmd("IFS=$'\n';for dir in $(ls -1d " mount_point "*/);do rmdir \"${dir}\";done",
          "Failed to trmove subdirectories of "mount_point, 253)
# Get the number of defined loop devices
  max_loops  = cmd_result("ls /dev/loop* | wc -w", "", 0)
# Get the number of loop devices currently in use
  loops_used = cmd_result("grep -w loop= /etc/mtab | wc -l", "", 0)
# Quit now if there are no loop devices available
  if (loops_used >= max_loops) {
    printf("%s%s: All available loop devices (%d  of them) are in use.%s\n", red, exe, max_loops, reset)
    exit(0)
  }
# Get the list of ISO files to be mounted into a temporary file
  tmp_dir="/tmp/mount-" ENVIRON["LOGNAME"]
  run_cmd("mkdir -p " tmp_dir, "Failed to create " tmp_dir, 1)
# Build the list of entries in the source directory
  temp=tmp_dir "/iso_list"
  run_cmd("touch " temp, "Unable to create the temporary file " temp, 2)
  list="ls -1 " loc " > " temp
  run_cmd("ls -1 " loc " > " temp, "system(" list ") call failed.", 3)
# Mount as many of the iso9660 images as possible
  while ((getline source < temp)) {
    if (mount_an_iso_file(source, mount_point)) {
      break
    }
  }
# All done.
  clean_exit(0)
}
# Run a command, printing and TTY output in blue.
# Print a red message to stderr and call the specified "clean_exit" on failure
function run_cmd(cmd, error_message, exit_code) {
  printf("%s", blue)
  if (system(cmd)) {
    printf("%s", reset)
    if (error_message != "") print red exe ": " error_message reset> "/dev/stderr"
    if (exit_code != 0) clean_exit(exit_code)
    return 1
  }
  printf("%s", reset)
  return 0
}
# Run a command and rerurn its output
function cmd_result(cmd, error_message,  result) {
  printf("%s", blue)
  cmd | getline result
  close(cmd)
  printf("%s", reset)
  if ( (! result) && error_message) {
    print red exe ": " error_message reset > "/dev/stderr"
  }
  return result
}
# Do initiaal clean-up (code < 0), or remove the temporary file and directory and exit with the psecified code
function clean_exit(code) {
# If here, error or normal exit. Delete the temporary file and directory.
  if (temp) close(temp)
  run_cmd("[ -e " tmp_dir " ] && rm -rf " tmp_dir, "Failed to remove " tmp_dir, 0)
  exit(code)
}
# Return 1 if all loop devices are in use
function mount_an_iso_file(location, under,  name,root,path,test) {
# Do we have any loop devices left?
  if (loops_used >= max_loops) {
    return 1
  }
# Find the current entry's name
  name=cmd_result("basename \"" location "\"", "Failed to find the basename of \"" location ".\"")
  if (name=="") {
    return ""
  }
# Where should this entry be mounted?
  root = under "\"" gensub(/\.iso$/,"","no",name) "\""
# Is the entry a iso9660 image?
  path = loc "/\"" name "\""
  test = cmd_result("file " path)
  if (test !~ /ISO 9660/) {
    return ""
  }
# Is it already mounted? (Look at /etc/mtab to see why we're replacing blanks by "\040".)
# Note that we go through two levels of "backslash resolution" before the command is processed
  test=cmd_result("grep " gensub(/ /,"\\\\\\\\\\\\040","g",root) " /etc/mtab")
  if (test != "") {
    return ""
  }
# Create the mount point if it doesn't already exist
  if (run_cmd("mkdir -p " root,"Failed to create directory " root, 0)) {
    return ""
  }
# Mount the file system.
  if (run_cmd("mount -t iso9660 -o loop,ro,defaults " path " " root, "Failed to mount " path " on " root, 0)==0) {
    print path " has been mounted on " root "."
    ++loops_used
  }
  else {
# Remove the mount point if the mount failed. (If the mount point is in use, this will fail.)
    run_cmd("rmdir " root, "", 0)
  }
  return ""
}


grail 11-16-2010 07:56 PM

So I have suggestions and questions:

1. if (exe=="") exe="rc.mount_iso_images.gawk" - This will always be true so the if test here is not required.

2. in_root=cmd_result("groups | grep -w root") - Personally I would use 'id -u' as it is less ambiguous (ie what if something strange, groups = a.root)

3. cmd_result and run_cmd - again I see a lot of similarities where a single function could easily handle both

4. loc and mount_point - see number 1

5. run_cmd("ls -1 " loc " > " temp, "system(" list ") call failed.", 3) - as list equals "ls -1 " loc " > " temp, should this not be:
Code:

run_cmd(list, "system(" list ") call failed.", 3)
6. mount_an_iso_file - this function is only ever called once with 2 parameters and yet the signature for the function has 6 parameters??

7. if (loops_used >= max_loops) - do you really need to use global variables in this test? Or maybe the test could be somehow implemented in the while loop calling the function?

8. name=cmd_result("basename \"" location "\"", "Failed to find the basename of \"" location ".\"") - not sure you need to go out to the shell to perform this task. gensub maybe?

9. Would you explain the following as I didn't understand the need for the replacement?:
Code:

# Is it already mounted? (Look at /etc/mtab to see why we're replacing blanks by "\040".)
# Note that we go through two levels of "backslash resolution" before the command is processed
  test=cmd_result("grep " gensub(/ /,"\\\\\\\\\\\\040","g",root) " /etc/mtab")

I hope you take all the above as intended, ie positive feedback :)

PTrenholme 11-17-2010 01:32 PM

grail, again. thanks for the feedback! :)

Here's the bash function used to call the gawk program from rc.local. As you can see, the variables you refer to in points 1 & 4 are set in the call, so they are, in fact, not always null. (The test is used to set default values if the variables are not set in the command line.)
Code:

#############################################################################
#
# Mount all ISO 9660 images found in /ISO under /mnt/ISO/
#
#############################################################################
function mount_iso() {
  /bin/gawk -v exe=mount_iso -v loc=/ISO -v mount_point=/mnt/ISO/ -f /etc/rc.d/rc.mount_iso_images.gawk
}

Point 2: Yes, using if (cmd_result("id -nu") != "root") would be a better test. I'll make that change in version 1.1.

Point 3: The difference is that cmd_result return the result, whilst run_cmd returns the error code. I'm more comfortable with that separation, but I can see your point.

Point 5: Yes, it would be clearer that way.

Point 6: Note the extra spaces before the other "parameters." Remember that gawk functions are called by value, and that anything listed in the argument list "shadows" variables with the same name that would otherwise be "visible" in the function. Since gawk has no "local" (nor "global") directive, placing "unpassed" variables in the argument list is the conventional way to declare local variables. The extra spaces, by convention, denote the start of the local variable list.

Point 7: I think I need the test there since loops_used is only incremented in the function, but it could be done outside. Either works.

P0int 8: Perhaps, but the shell function is fairly fast, and the run_cmd function already available.

Point 9: Here's what the /etc/mtab looks like when the file name contains blanks. I believe that the \040 in that output is literal.
Code:

/ISO/1635\040-\040The\040Eastern\040Front.iso /mnt/ISO/1635\040-\040The\040Eastern\040Front iso9660 ro,loop=/dev/loop0 0 0
/ISO/At\040All\040Costs.iso /mnt/ISO/At\040All\040Costs iso9660 ro,loop=/dev/loop1 0 0
/ISO/Cryoburn.iso /mnt/ISO/Cryoburn iso9660 ro,loop=/dev/loop2 0 0
/ISO/Ghost.iso /mnt/ISO/Ghost iso9660 ro,loop=/dev/loop3 0 0
/ISO/Looking\040Glass.iso /mnt/ISO/Looking\040Glass iso9660 ro,loop=/dev/loop4 0 0
/ISO/Mission\040of\040Honor.iso /mnt/ISO/Mission\040of\040Honor iso9660 ro,loop=/dev/loop5 0 0
/ISO/Storm\040from\040the\040Shadows.iso /mnt/ISO/Storm\040from\040the\040Shadows iso9660 ro,loop=/dev/loop6 0 0
/ISO/The\040Best\040of\040Jim\040Baens\040Universe.iso /mnt/ISO/The\040Best\040of\040Jim\040Baens\040Universe iso9660 ro,loop=/dev/loop7 0 0
/ISO/The\040Claws\040that\040Catch.iso /mnt/ISO/The\040Claws\040that\040Catch iso9660 ro,loop=/dev/loop8 0 0
/ISO/The\040Far\040Side\040of\040the\040Stars.iso /mnt/ISO/The\040Far\040Side\040of\040the\040Stars iso9660 ro,loop=/dev/loop9 0 0
/ISO/The\040Spider.iso /mnt/ISO/The\040Spider iso9660 ro,loop=/dev/loop10 0 0
/ISO/This\040Scepter'd\040Isle.iso /mnt/ISO/This\040Scepter'd\040Isle iso9660 ro,loop=/dev/loop11 0 0
/ISO/Windrider's\040Oath.iso /mnt/ISO/Windrider's\040Oath iso9660 ro,loop=/dev/loop12 0 0


grail 11-17-2010 07:49 PM

Thanks for the explanation on Point 6 ... this makes sense now :)

How does the \040 in Point 9 benefit the script? (sorry if I am not getting this one :( )

Lastly, on calling the script may i also suggest:
Code:

/etc/rc.d/rc.mount_iso_images.gawk -v exe=mount_iso -v loc=/ISO -v mount_point=/mnt/ISO/
Assuming script is executable ;)

PTrenholme 11-18-2010 11:15 AM

Note the first line of the script (/bin/gawk -f). The -f tells it that everything following from /dev/stdin is part of the code, so the -v ... on the command line cause syntax errors. You can use the built-in ARGC array to read argument values, but I found it awkward to do so without some somewhat convoluted code, so I opted for using the bash invocation. After all, rc.local is a bash program.

As to the \040, note that a cat /etc/mtab displays a literal \040 for the blank, not the ASCII blank that an octal 40 represents. So, to get grep to match in mtab when the file name contains a blank, I needed to replace the blank by literal \040 strings. (There may be an easier way to check to see if a specific file has been mounted, but that seemed to work.) Note that the program starts by un-mounting all iso9660 mounts and deleting any sub-directories of mount_poit, so the check may be redundant. I had put it in during development, and felt it was safer to leave it in the "final" code.

grail 11-18-2010 06:29 PM

Quote:

The -f tells it that everything following from /dev/stdin is part of the code, so the -v ... on the command line cause syntax errors.
I understand the -f, but on my gawk (3.1.8) the line I showed you works just fine with the -v options ... go figure.
To show you my test case, I used the following:
Code:

#!/usr/bin/awk -f

BEGIN{ print name }

And ran the following:
Code:

$./test.awk -v name=grail
grail

Quote:

As to the \040, note that a cat /etc/mtab displays a literal \040 for the blank, not the ASCII blank that an octal 40 represents.
uummm .. again, on my machine if I do cat /etc/mtab the spaces are just spaces (ie no literal \040)??
But at least now I understand why necessary for your machine :)


All times are GMT -5. The time now is 02:57 AM.