Truncate a file: Difference between revisions

Add C for Windows.
(Add C for Windows.)
Line 2:
 
The task is to demonstrate how to truncate a file to a specific length. This should be implemented as a routine that takes two parameters: the filename and the required file length (in bytes). Truncation can be achieved using system or library calls intended for such a task, if such methods exist, or by creating a temporary file of a reduced size and renaming it, after first deleting the original file, if no other method is available. The file may contain non human readable binary data in an unspecified format, so the routine should be "binary safe", leaving the contents of the untruncated part of the file unchanged. If the specified filename does not exist, or the provided length is not less than the current file length, then the routine should raise an appropriate error condition and exit. On some systems, the provided file truncation facilities might not change the file or may extend the file, if the specified length is greater than the current length of the file. For the purpose of this task, it is permissible for such facilities to be used. Such behaviour should be noted, or optionally a warning message relating to an non change or increase in file size may be implemented.
 
=={{header|C}}==
Windows uses <code>SetEndOfFile()</code> to change the length of a file. This program can truncate or extend a file. It can detect and print errors.
 
* If the file does not exist: "The system cannot find the file specified."
* If the length is negative: "An attempt was made to move the file pointer before the beginning of the file."
* If the length is too large: "There is not enough space on the disk."
 
{{works with|MinGW}}
<lang c>#include <windows.h>
#include <stdio.h>
#include <wchar.h>
 
/* Print "message: last Win32 error" to stderr. */
void
oops(const wchar_t *message)
{
wchar_t *buf;
DWORD error;
 
buf = NULL;
error = GetLastError();
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, error, 0, (wchar_t *)&buf, 0, NULL);
 
if (buf) {
fwprintf(stderr, L"%ls: %ls", message, buf);
LocalFree(buf);
} else {
/* FormatMessageW failed. */
fwprintf(stderr, L"%ls: unknown error 0x%x\n",
message, error);
}
}
 
int
dotruncate(wchar_t *fn, LARGE_INTEGER fp)
{
HANDLE fh;
 
fh = CreateFileW(fn, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (fh == INVALID_HANDLE_VALUE) {
oops(fn);
return 1;
}
 
if (SetFilePointerEx(fh, fp, NULL, FILE_BEGIN) == 0 ||
SetEndOfFile(fh) == 0) {
oops(fn);
CloseHandle(fh);
return 1;
}
 
CloseHandle(fh);
return 0;
}
 
/*
* Truncate or extend a file to the given length.
*/
int
main()
{
LARGE_INTEGER fp;
int argc;
wchar_t **argv, *fn, junk[2];
 
/* MinGW never provides wmain(argc, argv). */
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
if (argv == NULL) {
oops(L"CommandLineToArgvW");
return 1;
}
 
if (argc != 3) {
fwprintf(stderr, L"usage: %ls filename length\n", argv[0]);
return 1;
}
 
fn = argv[1];
 
/* fp = argv[2] converted to a LARGE_INTEGER. */
if (swscanf(argv[2], L"%lld%1ls", &fp.QuadPart, &junk) != 1) {
fwprintf(stderr, L"%ls: not a number\n", argv[2]);
return 1;
}
 
return dotruncate(fn, fp);
}</lang>
 
==Icon and {{header|Unicon}}==
Anonymous user