171 lines
4.1 KiB
C
171 lines
4.1 KiB
C
/* $XConsortium: miscfuncs.c,v 1.7 94/12/01 17:15:05 kaleb Exp $ */
|
|
/* $XFree86: xc/programs/xmh/miscfuncs.c,v 3.6 2001/10/28 03:34:39 tsi 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 (*)(const void *, const void *))StrCmp);
|
|
|
|
return(i);
|
|
}
|