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