0

How can I copy a file without using standard C library functions in Linux? In other words, I would like to copy a file directly with system calls. Is it possible?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
kkk001
  • 31
  • 2
  • Yes, it's possible. Open the file for reading and the copy for writing.. The read and write. Use the non-standard low level platform specific functions if `fopen` etc aren't allowed. – Ted Lyngmo Dec 20 '21 at 22:15
  • Sure. What operating system are you programming for? – fuz Dec 20 '21 at 22:15
  • Sorry I dod not mentioned it. I want to do it in Linux 64. – kkk001 Dec 20 '21 at 22:16
  • 10
    Then use `open`, `read`, `write` and `close`. They are all in section `2` in the `man` pages. – Ted Lyngmo Dec 20 '21 at 22:17
  • 2
    It's almost as easy as `fopen`/`fread`/`fwrite`/`fclose`. (A smidge easier, actually: four fewer `f`'s to type, and one fewer argument to `read` and `write`, too! :-) ) – Steve Summit Dec 20 '21 at 22:18
  • @TedLyngmo: Technically, the normal way to use those from C are via the wrapper functions defined in `libc.so`; it's slightly ambiguous whether the querent means without any functions from libc, or without any functions that ISO C defines as "library" functions. There's some implication of the latter, in which case yes, POSIX standard functions would work fine. Otherwise you'd want to use a header that would actually inline the syscalls (with inline `asm` statements) so you don't need to link libc, such as https://github.com/linux-on-ibm-z/linux-syscall-support (has all arches, including x86 – Peter Cordes Dec 20 '21 at 23:41
  • @PeterCordes Yes, using syscalls would probably be an even safer way to score on this assignment. – Ted Lyngmo Dec 20 '21 at 23:48
  • To Peter's point: this question was originally tagged with [assembly], until I (perhaps wrongly) deleted it. – Steve Summit Dec 20 '21 at 23:58
  • @SteveSummit: Ah, that would make sense, then. Writing by hand in asm makes the difference between calling a function vs. calling the kernel directly more obvious than the normal C way of using a wrapper function for your inline asm. But if you know the system-calling convention ([What are the calling conventions for UNIX & Linux system calls (and user-space functions) on i386 and x86-64](https://stackoverflow.com/q/2535989)), you just need to know which system calls at all, and then you can look up their man pages to find where the args go, and call numbers from `unistd_64.h`. – Peter Cordes Dec 21 '21 at 00:54

1 Answers1

1

file directly with system calls. Is it possible?

In pseudocode, using sendfile:

int in = open("input", ...);
fstatat(in, &stat);
int out = open("output", ...);
sendfile(in, out, NULL, stat.st_size);
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • You should call `sendfile` in a loop. It may not send all the bytes, and in that case needs to be restarted. – HAL9000 Dec 20 '21 at 23:10
  • 2
    Also, note the man-page caution - `"Other Unix systems implement sendfile() with different semantics and prototypes. It should not be used in portable programs."` That said, if you do not need it to be portable, `sendfile()` is very fast and efficient due to the transfer being done in kernel space. – David C. Rankin Dec 20 '21 at 23:17
  • Fun fact: on Linux 5.3 and later, there's [`copy_file_range(2)`](https://man7.org/linux/man-pages/man2/copy_file_range.2.html) which takes two FDs, two offsets, and a length. But like sendfile, it can still return early with fewer bytes copied than requested, so should still be called in a loop. (The syscall was present since 4.5, but before 5.3 it would return -EXDEV if the files weren't on the same FS. I think it was originally intended for making CoW reflinks like on btrfs / zfs like `cp --reflink=auto` does, but now can fall back to an in-kernel copy.) Does sendfile do CoW? – Peter Cordes Dec 20 '21 at 23:48