Browse Source

Add `unlink` program

Matteo Savatteri 4 years ago
parent
commit
4fbf76abf4
3 changed files with 134 additions and 0 deletions
  1. 29 0
      4_unlink/Makefile
  2. 18 0
      4_unlink/README.md
  3. 87 0
      4_unlink/src/unlink.s

+ 29 - 0
4_unlink/Makefile

@@ -0,0 +1,29 @@
+MAIN=unlink
+
+AS=as
+ASFLAGS=
+LD=ld
+LDFLAGS=
+
+SDIR=src
+ODIR=obj
+BDIR=bin
+
+
+$(BDIR)/$(MAIN): $(ODIR)/$(MAIN).o $(BDIR)
+	$(LD) -o $@ $(ODIR)/$(MAIN).o $(LDFLAGS)
+$(BDIR):
+	mkdir $(BDIR)
+
+$(ODIR)/$(MAIN).o: $(SDIR)/$(MAIN).s $(ODIR)
+	$(AS) -o $@ $(SDIR)/$(MAIN).s $(ASFLAGS)
+$(ODIR):
+	mkdir $(ODIR)
+
+
+.PHONY: clean clen-all
+
+clean:
+	rm -rf $(ODIR)
+clean-all:
+	rm -rf $(ODIR) $(BDIR)

+ 18 - 0
4_unlink/README.md

@@ -0,0 +1,18 @@
+# unlink
+Call the unlink function to remove the specified file.
+
+## Description
+The program `unlink` asks the kernel to unlink the file
+whose name is specified as the second command line argument
+by the mean of the `sys_unlinkat` system call.
+## Usage
+`$ unlink FILE`
+
+## Comment
+My first attempt to implement error reporting, hurrey!
+
+### How to Understand Errors
+The `unlink` program reports system error numbers writing them
+to `stderr`. The meaning of the codes is specified in the header
+files `/include/uapi/asm-generic/errno{,-base}.h` found in the
+kernel source tree. 

+ 87 - 0
4_unlink/src/unlink.s

@@ -0,0 +1,87 @@
+.text					# Section for machine istructions to be executed
+	.global _start			# Needed by ld to find his default entry point
+_start:					# _start symbol
+					# cmdline check
+	pop	%rax			# Put number of arguments in %rax register
+	cmp	$2, %rax		# Must be 2 arguments (1+executable name)
+	jne	exit_cmd_line_error	# jump to error if not equal
+
+	mov	$263, %rax		# Put "263" in %rax register. 263 = sys_unlinkat call.
+	mov	$-100, %rdi		# dirfd of directory for relative paths. -100 = AT_FDCWD
+					# special for current working directory
+	mov	8(%rsp), %rsi		# Put address of string that is the name of the file
+					# to unlink in %rsi register. This is expected to be
+					# the second cmdline argument of this program and is
+					# found at %rsp + 64bit (=8byte) after the pop above.
+	xor	%rdx, %rdx		# Zero %rdx register = no special flags for call
+	syscall				# Ask Linux to perform syscall index by rax
+
+	test	%rax, %rax		# Test if return value of syscall in %rax register is
+					# zero
+	jz	exit_zero		# If yes, exit zero
+
+	neg	%rax			# If not negate error value (linux return negative numbers
+					# in %rax for system error (range -4096:-1)
+	mov	$10, %bl		# Set to "10" the 8 low bits od %rbx register
+
+	div	%bl			# "div" istruction works like this in this case:
+					# %ax : %bl = %al (quotient) + %ah (reminder)
+					# NOTE: the negated error value of sys_unlink is expected to
+					# be *in any case* a number of two digits in decimal base.
+					# If I divide it by "10" the quotient is the first digit
+					# and the reminder is the second one (from left to right)
+	mov	$48, %bl		# Put ASCII "0" in 8 low bits of %rbx register
+	add	%bl, %al		# Add ASSCII "0" one digit number in 0-byte of %rax register
+	add	%bl, %ah		# Add ASSCII "0" one digit number in 1-byte of %rax register
+	push	%ax			# Push 16 low bits of %rax register (contains concatened ASCII
+					# bits for the two digits of our error code)
+
+	movb	$0x0A, 2(%rsp)		# Put an "endline" at %rsp + 16bit. (Put "\n" ASCII code
+					# in stack just after the digits of our error code).
+					# (All this is to avoid 2 sys_write calls above)
+
+					# Write generic part of system error message to stderr
+	mov	$1, %rax
+	mov	$1, %rdi
+	mov	$err_msg, %rsi
+	mov	$13, %rdx
+	syscall
+
+	mov	$1, %rax		# Write error code digits + endline to stderr
+	mov	$1, %rdi
+	lea	(%rsp), %rsi
+	mov	$3, %rdx
+	syscall
+
+	mov	$1, %rdi		# Put "1" in $rax %rdi register. (1= exit code)
+	jmp	exit			# Exit
+
+print_help:				# Print cmdline help to stdout
+	mov	$1, %rax
+	mov	$1, %rdi
+	mov	$help_msg, %rsi
+	mov	$19, %rdx
+	syscall
+
+	ret				# Return to main program execution
+
+exit:					# Ask kernel to terminate execution with some exit
+					# code
+	mov	$60, %rax		# Put "60" in %rax register. 60 = sys_exit call
+					# exit status argument of sys_exit.
+	syscall				# Ask Linux to perform syscall indexed by %rax
+
+exit_zero:				# Exit with 0 exit code
+	xor	%rdi, %rdi		# Set %rdi register to "0".
+	jmp	exit			# Jump to "exit" routine
+
+exit_cmd_line_error:			# Exit with 1 exit code printing cmdline help
+	call	print_help		# Call print_help function
+	mov	$1, %rdi		# Put "1" exit code in %rdi register
+	jmp	exit			# Jump to "exit" routine
+
+.section .rodata
+	help_msg:			# 19 bytes; cmdline help message
+		.ascii "Usage: unlink FILE\n"
+	err_msg:			# 13 bytes; generic string for system error
+		.ascii "System error "