blob: fd3e0e9f42fbad946617f649838541bed75c16d2 [file] [log] [blame] [raw]
/* A part of the Windows CE C Extra Library (celibc)
Copyright 2007-2015 PC GO Ld.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
#include <unistd.h>
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#define ZERO_BUFFER_SIZE (512)
int ftruncate(int fd, off_t length) {
off_t current = lseek(fd, 0, SEEK_CUR);
if(current == -1) return -1;
off_t current_eof = lseek(fd, 0, SEEK_END);
if(current_eof == -1) return -1;
off_t offset = length - current_eof;
if(offset < 0) {
if(lseek(fd, length, SEEK_SET) == -1) goto failed;
if(!SetEndOfFile((void *)fd)) goto failed;
} else if(offset > 0) {
void *buffer = malloc(ZERO_BUFFER_SIZE);
if(!buffer) goto failed;
memset(buffer, 0, ZERO_BUFFER_SIZE);
while(offset > 0) {
int s = write(fd, buffer, ZERO_BUFFER_SIZE < offset ? ZERO_BUFFER_SIZE : offset);
if(s < 0) {
free(buffer);
goto failed;
}
offset -= s;
}
free(buffer);
}
lseek(fd, current, SEEK_SET);
return 0;
failed: ;
int e = errno;
lseek(fd, current, SEEK_SET);
errno = e;
return -1;
}
int truncate(const char *path, off_t length) {
if(!path) {
errno = EFAULT;
return -1;
}
if(length < 0) {
errno = EINVAL;
return -1;
}
if(!*path) {
errno = ENOENT;
return -1;
}
int fd = open(path, O_WRONLY);
if(fd == -1) return -1;
int r = ftruncate(fd, length);
int e = errno;
if(close(fd) < 0) return -1;
errno = e;
return r;
}