1 /* $Id: compat.cc,v 1.4 2005/07/09 19:14:46 atterer Exp $ -*- C++ -*-
3 |_) /| Copyright (C) 2001-2003 | richard@
4 | \/¯| Richard Atterer | atterer.net
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2. See
8 the file COPYING for details.
10 Cross-platform compatibility
27 //______________________________________________________________________
30 // No additional code required
31 //______________________________________________________________________
34 // Truncate using native Windows API
35 int compat_truncate(const char* path, uint64 length) {
36 // TODO error handling: GetLastError(), FormatMessage()
37 HANDLE handle = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, 0,
38 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
39 if (handle == INVALID_HANDLE_VALUE) return -1;
41 LARGE_INTEGER targetFileLen;
42 targetFileLen.QuadPart = length;
43 LARGE_INTEGER newFileLen;
44 if (SetFilePointerEx(handle, targetFileLen, &newFileLen, FILE_BEGIN) == 0
45 || SetEndOfFile(handle) == 0U) {
49 Assert(static_cast<uint64>(newFileLen.QuadPart) == length);
50 if (CloseHandle(handle) == 0) return -1;
53 //______________________________________________________________________
55 #elif !HAVE_TRUNCATE && HAVE_FTRUNCATE
56 // Truncate using POSIX ftruncate()
57 #include <sys/types.h>
60 #include <unistd-jigdo.h>
62 # define O_LARGEFILE 0 // Linux: Allow 64-bit file sizes on 32-bit arches
64 int compat_truncate(const char* path, uint64 length) {
65 int fd = open(path, O_RDWR | O_LARGEFILE);
66 if (fd == -1) return -1;
67 if (ftruncate(fd, length) != 0) { close(fd); return -1; }
70 //______________________________________________________________________
73 # error "No implementation for truncating files!"
75 //====================================================================
78 // Delete destination before renaming
79 int compat_rename(const char* src, const char* dst) {
80 remove(dst); // Ignore errors
81 return rename(src, dst);
84 //====================================================================
86 #if !WINDOWS && !HAVE_SETENV
89 /* Like less<>, but only compares up to the first '=' in the string. All
90 *strings must* contain a '='. */
91 bool operator()(const string& x, const string& y) const {
92 string::const_iterator xx = x.begin(), yy = y.begin();
97 if (a == '=') return b != '=';
99 if (b == '=') return false;
105 /* This is probably a candidate for the least efficient setenv-via-putenv
106 implementation ever. */
107 bool compat_setenv(const char* name, const char* value) {
108 typedef set<string, CmpTilEq> VarSet;
113 VarSet::iterator old = vars.find(var);
114 if (old != vars.end()) vars.erase(old);
115 pair<VarSet::iterator,bool> ins = vars.insert(var);
116 return putenv(const_cast<char*>(ins.first->c_str())) == 0 ?
120 //====================================================================
122 #if !WINDOWS && HAVE_IOCTL_WINSZ && HAVE_FILENO
123 #include <sys/ioctl.h>
127 if (ioctl(fileno(stderr), TIOCGWINSZ, &w) == -1
132 //====================================================================
135 int compat_compare(const string& s1, string::size_type pos1,
136 string::size_type n1, const string& s2, string::size_type pos2 = 0,
137 string::size_type n2 = string::npos) {
138 string::size_type r1 = s1.length() - pos1;
139 if (r1 > n1) r1 = n1;
140 string::size_type r2 = s2.length() - pos2;
141 if (r2 > n2) r2 = n2;
142 string::size_type r = r2;
144 if (rdiff < 0) r = r1;
145 string::const_iterator i1 = s1.begin() + pos1;
146 string::const_iterator i2 = s2.begin() + pos2;
148 if (*i1 < *i2) return -1;
149 if (*i1 > *i2) return 1;
157 //====================================================================
159 #if !HAVE_STRINGSTRCMP
160 int compat_compare(const string& s1, string::size_type pos1,
161 string::size_type n1, const char* s2,
162 string::size_type n2 = string::npos) {
163 string::size_type r1 = s1.length() - pos1;
164 if (r1 > n1) r1 = n1;
165 string::size_type r2 = strlen(s2);
166 if (r2 > n2) r2 = n2;
167 string::size_type r = r2;
169 if (rdiff < 0) r = r1;
170 string::const_iterator i1 = s1.begin() + pos1;
173 if (*i1 < *i2) return -1;
174 if (*i1 > *i2) return 1;