truncate.c 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. /* truncate.c - set file length, extending sparsely if necessary
  2. *
  3. * Copyright 2011 Rob Landley <rob@landley.net>
  4. USE_TRUNCATE(NEWTOY(truncate, "<1s:|c", TOYFLAG_USR|TOYFLAG_BIN))
  5. config TRUNCATE
  6. bool "truncate"
  7. default y
  8. help
  9. usage: truncate [-c] -s SIZE file...
  10. Set length of file(s), extending sparsely if necessary.
  11. -c Don't create file if it doesn't exist
  12. -s New size (with optional prefix and suffix)
  13. SIZE prefix: + add, - subtract, < shrink to, > expand to,
  14. / multiple rounding down, % multiple rounding up
  15. SIZE suffix: k=1024, m=1024^2, g=1024^3, t=1024^4, p=1024^5, e=1024^6
  16. */
  17. #define FOR_truncate
  18. #include "toys.h"
  19. GLOBALS(
  20. char *s;
  21. long size;
  22. int type;
  23. )
  24. static void do_truncate(int fd, char *name)
  25. {
  26. long long size;
  27. if (fd<0) return;
  28. if (TT.type == -1) size = TT.size;
  29. else {
  30. size = fdlength(fd);
  31. if (TT.type<2) size += TT.size*(1-(2*TT.type));
  32. else if (TT.type<4) {
  33. if ((TT.type==2) ? (size <= TT.size) : (size >= TT.size)) return;
  34. size = TT.size;
  35. } else {
  36. size = (size+(TT.type-4)*(TT.size-1))/TT.size;
  37. size *= TT.size;
  38. }
  39. }
  40. if (ftruncate(fd, size)) perror_msg("'%s' to '%lld'", name, size);
  41. }
  42. void truncate_main(void)
  43. {
  44. int cr = !FLAG(c);
  45. if (-1 != (TT.type = stridx("+-<>/%", *TT.s))) TT.s++;
  46. TT.size = atolx(TT.s);
  47. // Create files with mask rwrwrw.
  48. // Nonexistent files are only an error if we're supposed to create them.
  49. loopfiles_rw(toys.optargs, O_WRONLY|O_CLOEXEC|(cr ? O_CREAT|WARN_ONLY : 0),
  50. 0666, do_truncate);
  51. }