nopen.c 5.39 KB
Newer Older
1
/* Network open functions (nopen and fnopen) and friends */
2 3 4 5 6

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
7
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

22 23 24
#include "filewrap.h"
#include "sockwrap.h"
#include "sbbsdefs.h"
25 26

/****************************************************************************/
27 28 29 30
/* Network open function. Opens all files DENYALL, DENYWRITE, or DENYNONE	*/
/* depending on access, and retries LOOP_NOPEN number of times if the		*/
/* attempted file is already open or denying access  for some other reason. */
/* All files are opened in BINARY mode.										*/
31
/****************************************************************************/
rswindell's avatar
rswindell committed
32
int nopen(const char* str, int access)
33 34 35 36 37
{
	int file,share,count=0;

    if(access&O_DENYNONE) {
        share=SH_DENYNO;
38 39 40 41 42 43
        access&=~O_DENYNONE; 
	} 
	else if((access&~(O_TEXT|O_BINARY))==O_RDONLY) 
		share=SH_DENYWR;
    else 
		share=SH_DENYRW;
44 45

#if !defined(__unix__)	/* Basically, a no-op on Unix anyway */
46 47
	if(!(access&O_TEXT))
		access|=O_BINARY;
48
#endif
49
    while(((file=sopen(str,access,share,DEFFILEMODE))==-1)
50
        && (errno==EACCES || errno==EAGAIN || errno==EDEADLOCK) && count++<LOOP_NOPEN)
51 52 53 54
        if(count)
            mswait(100);
    return(file);
}
55

56 57 58 59
/****************************************************************************/
/* This function performs an nopen, but returns a file stream with a buffer */
/* allocated.																*/
/****************************************************************************/
rswindell's avatar
rswindell committed
60
FILE* fnopen(int* fd, const char* str, int access)
61
{
62
	char*	mode;
63 64
	int		file;
	FILE *	stream;
65

66 67 68 69 70 71 72
    if((file=nopen(str,access))==-1)
        return(NULL);

    if(fd!=NULL)
        *fd=file;

    if(access&O_APPEND) {
deuce's avatar
deuce committed
73
        if((access&O_RDWR)==O_RDWR)
74
            mode="a+";
75
        else
76
            mode="a"; 
77
	} else if(access&(O_TRUNC|O_WRONLY)) {
deuce's avatar
deuce committed
78
		if((access&O_RDWR)==O_RDWR)
79
			mode="w+";
80
		else
81
			mode="w";
82
	} else {
deuce's avatar
deuce committed
83
        if((access&O_RDWR)==O_RDWR)
84
            mode="r+";
85
        else
86
            mode="r"; 
87 88 89 90 91 92 93 94 95
	}
    stream=fdopen(file,mode);
    if(stream==NULL) {
        close(file);
        return(NULL); 
	}
    setvbuf(stream,NULL,_IOFBF,FNOPEN_BUF_SIZE);
    return(stream);
}
rswindell's avatar
rswindell committed
96 97 98 99

BOOL ftouch(const char* fname)
{
	int file;
100
	struct utimbuf ut;
rswindell's avatar
rswindell committed
101

102
	/* update the time stamp */
103 104
	ut.actime = ut.modtime = time(NULL);
	if(utime(fname, &ut)==0)
105
		return TRUE;
106 107 108

	/* create the file */
	if((file=nopen(fname,O_WRONLY|O_CREAT))<0)
109
		return FALSE;
110
	close(file);
111
	return TRUE;
rswindell's avatar
rswindell committed
112
}
113

114
BOOL fmutex(const char* fname, const char* text, long max_age)
115 116
{
	int file;
rswindell's avatar
rswindell committed
117
	time_t t;
118
#if !defined(NO_SOCKET_SUPPORT)
119
	char hostname[128];
120 121 122
	if(text==NULL && gethostname(hostname,sizeof(hostname))==0)
		text=hostname;
#endif
123

124 125
	if(max_age && (t=fdate(fname)) >= 0 && (time(NULL)-t) > max_age) {
		if(remove(fname)!=0)
126
			return FALSE;
127
	}
128
	if((file=open(fname,O_CREAT|O_WRONLY|O_EXCL,DEFFILEMODE))<0)
129
		return FALSE;
130 131 132
	if(text!=NULL)
		write(file,text,strlen(text));
	close(file);
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 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
	return TRUE;
}

BOOL fcompare(const char* fn1, const char* fn2)
{
	FILE*	fp1;
	FILE*	fp2;
	BOOL	success=TRUE;

	if(flength(fn1) != flength(fn2))
		return FALSE;
	if((fp1=fopen(fn1,"rb"))==NULL)
		return FALSE;
	if((fp2=fopen(fn2,"rb"))==NULL) {
		fclose(fp1);
		return FALSE;
	}

	while(!feof(fp1) && success) {
		if(fgetc(fp1) != fgetc(fp2))
			success=FALSE;
	}

	fclose(fp1);
	fclose(fp2);

	return(success);
}


/****************************************************************************/
/****************************************************************************/
BOOL backup(const char *fname, int backup_level, BOOL ren)
{
	char	oldname[MAX_PATH+1];
	char	newname[MAX_PATH+1];
	char*	ext;
	int		i;
	int		len;

	if(flength(fname) < 1)	/* no need to backup a 0-byte (or non-existent) file */
		return FALSE;

	if((ext=strrchr(fname,'.'))==NULL)
		ext="";

	len=strlen(fname)-strlen(ext);

	for(i=backup_level;i;i--) {
		safe_snprintf(newname,sizeof(newname),"%.*s.%d%s",len,fname,i-1,ext);
		if(i==backup_level)
			if(fexist(newname) && remove(newname)!=0)
				return FALSE;
		if(i==1) {
			if(ren == TRUE) {
				if(rename(fname,newname)!=0)
					return FALSE;
			} else {
				struct utimbuf ut;

				/* preserve the original time stamp */
				ut.modtime = fdate(fname);

196
				if(!CopyFile(fname, newname, /* failIfExists: */FALSE))
197 198 199 200 201 202 203 204 205 206 207 208 209
					return FALSE;

				ut.actime = time(NULL);
				utime(newname, &ut);
			}
			continue; 
		}
		safe_snprintf(oldname,sizeof(oldname),"%.*s.%d%s",len,fname,i-2,ext);
		if(fexist(oldname) && rename(oldname,newname)!=0)
			return FALSE;
	}

	return TRUE;
210
}