I've been recently learning a lot about systems programming/operating systems 
using the Linux Programming Interface book, and I've been trying to translate 
the C code it has to Nim. The POSIX library feels pretty great, eventually I'm 
hoping to not use it and just replace the workflows with the higher level 
standard libraries (os,typedthreads,etc.).

I've also been reading the Operating Systems in 3 Pieces book, which I thought 
was pretty nice.

Though I recently saw someone post that they had built a kernel (I believe with 
Nim) and now all I have are more questions as to how someone interacts at such 
a low level by creating their own syscalls.

I just think the lower level we go the cooler things become. I'll have to watch 
the showcase video to find more.

Anyway, I wanted to showcase a bit of my work thus far. I recently touched on 
the `lseek()` syscall and thought it was interesting to witness how file holes 
are made. Here's a script in Nim that allows you to create/open a file to read 
and write with. Depending on whether or not you use `s` in your command line 
argument it will try and move things around based on a pointer within a 
sequence (buffer):
    
    
    import posix, os, strutils, sequtils
    
    var
      length, fd, j: cint
      numRead,numWritten: int
      offset,offSetSetting: Off
      buf: seq[byte]
      bufPtr: ptr byte
    
    if paramCount() < 0 or cmpIgnoreCase(paramStr(0),"--help") == 0:
      quit("./seek_io file {r<length> | R<length> | w<string> | s<offset>} 
...\n")
    
    fd = posix.open(paramStr(1).cstring, O_RDWR or O_CREAT, S_IRUSR or S_IRGRP 
or SIWGRP or S_IROTH or S_IWOTH)
    
    if fd == -1:
      quit("Cannot open file:" & paramStr(1))
    
    for ap in 1..paramCount():
      case paramStr(ap)[0]:
        of 'r','R':
          length = parseInt((paramStr(ap)[1..^1])).cint
          buf.setLen(length)
          bufPtr = addr buf[0]  #This needs to be here because the buffer needs 
to be filled beforehand
          
          numRead = posix.read(fd, bufPtr, length)
          if numRead == -1:
            quit("Failed to read file, data:" & cast[string](buf))
        
        of 'w':
          var inputString = paramStr(ap)[1..^1].toSeq()
          var strPtr: ptr char = addr inputString[0] # This needs to point to 
the first element
          numWritten = posix.write(fd, strPtr, inputString.len())
          if numWritten == -1:
            quit("Failed to write to file")
        
        of 's':
          offset = parseInt(paramStr(ap)[1..^1]).Off
          offsetSetting = posix.lseek(fd, offset,SEEK_SET)
          if offSetSetting == -1:
            quit("Failed to offset by ", offset)
        
        else:
          discard
    
    
    Run

I didn't use any functional programming paradigms or anything fancy because I'm 
still new to that too. But uh... I think this works alright. The way you use it 
is like an example below:

`$./seek_io testfile s100 wBart`

It will create a sparse file called `testfile` and you can run `cat` on it to 
check the contents. I just thought it was cool. It's just a direct translation 
of the code I saw in the book.

Reply via email to