1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
/* $XConsortium: miscfuncs.c,v 1.7 94/12/01 17:15:05 kaleb Exp $ */
/* $XFree86: xc/programs/xmh/miscfuncs.c,v 3.7 2002/04/05 21:06:28 dickey Exp $ */
#include "xmh.h"
#include <X11/Xos.h>
#ifndef X_NOT_POSIX
#include <dirent.h>
#else
#ifdef SYSV
#include <dirent.h>
#else
#ifdef USG
#include <dirent.h>
#else
#include <sys/dir.h>
#ifndef dirent
#define dirent direct
#endif
#endif
#endif
#endif
#include <stdlib.h>
#if defined(SYSV) && (defined(i386) || defined(MOTOROLA))
/* These systems don't have the ftruncate() system call, so we emulate it.
* This emulation can only shorten, not lengthen.
* For convenience, we pass in the name of the file, even though the
* real ftruncate doesn't.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#define CHUNKSIZE 1024
int ftruncate_emu(
int fd,
off_t length,
char *name)
{
char tmp_file[15];
int new_fid, bytes_left, i;
unsigned char buffer[CHUNKSIZE];
struct stat stat_val;
/* Open a temp file. */
sprintf(tmp_file, ".xmhtmp%d~", getpid());
(void) unlink(tmp_file);
new_fid = open(tmp_file, O_RDWR | O_CREAT);
lseek(fd, (off_t)0, 0);
/* Copy original file to temp file. */
for (i = 0; i < length / CHUNKSIZE; i++) {
if (read(fd, buffer, CHUNKSIZE) != CHUNKSIZE) {
(void)fprintf(stderr, "xmh: read error in ftruncate emulation\n");
return -1;
}
else if (write(new_fid, buffer, CHUNKSIZE) != CHUNKSIZE) {
(void)fprintf(stderr, "xmh: write error in ftruncate emulation\n");
return -1;
}
}
bytes_left = length % CHUNKSIZE;
if (read(fd, buffer, bytes_left) != bytes_left) {
(void)fprintf(stderr, "xmh: read error in ftruncate() emulation\n");
return -1;
}
else if (write(new_fid, buffer, bytes_left) != bytes_left) {
(void)fprintf(stderr, "xmh: write error in ftruncate() emulation\n");
return -1;
}
/* Set mode of temp file to that of original file. */
(void) fstat(fd, &stat_val);
(void) chmod(tmp_file, stat_val.st_mode);
/* Close files, delete original, rename temp file to original. */
myclose(new_fid);
myclose(fd);
(void) unlink(name); /* remove original */
(void) rename(tmp_file, name); /* rename temp file */
/* If we weren't going to close the file right away in the one
place this is called from, we'd have to do something like this:
new_fid = myopen(name, O_RDWR, 0666);
if (new_fid != fd) {
dup2(new_fid, fd);
close(new_fid);
}
but the file does get closed, so we don't bother. */
return 0;
}
#endif /* SYSV variant that needs ftruncate emulation */
/*
** This code is by Rich Salz (rsalz@bbn.com), and ported to SVR4
** by David Elliott (dce@smsc.sony.com). No copyrights were found
** in the original. Subsequently modified by Bob Scheifler.
*/
/* A convenient shorthand. */
typedef struct dirent ENTRY;
/* Initial guess at directory size. */
#define INITIAL_SIZE 20
static int StrCmp(char **a, char **b)
{
return strcmp(*a, *b);
}
int
ScanDir(
char *Name,
char ***List,
int (*Selector)(char *))
{
register char **names;
register ENTRY *E;
register DIR *Dp;
register int i;
register int size;
/* Get initial list space and open directory. */
size = INITIAL_SIZE;
if (!(names = (char **)malloc(size * sizeof(char *))) ||
!(Dp = opendir(Name)))
return(-1);
/* Read entries in the directory. */
for (i = 0; (E = readdir(Dp)); )
if (!Selector || (*Selector)(E->d_name)) {
/* User wants them all, or he wants this one. */
if (++i >= size) {
size <<= 1;
names = (char**)realloc((char *)names, size * sizeof(char*));
if (!names) {
closedir(Dp);
return(-1);
}
}
/* Copy the entry. */
if (!(names[i - 1] = (char *)malloc(strlen(E->d_name) + 1))) {
closedir(Dp);
return(-1);
}
(void)strcpy(names[i - 1], E->d_name);
}
/* Close things off. */
names[i] = (char *)0;
*List = names;
closedir(Dp);
/* Sort? */
if (i)
qsort((char *)names, i, sizeof(char *), (int (*)())StrCmp);
return(i);
}
|