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