diff -U 5 -r -N oldsource/Makefile newsource/Makefile --- oldsource/Makefile Wed Dec 2 07:40:49 1998 +++ newsource/Makefile Fri Dec 4 08:53:23 1998 @@ -583,13 +583,13 @@ .c.o: $(INCLUDES) @echo Compiling $*.c @$(CC) $(CFLAGS) -c $(srcdir)$*.c -smbd: server.o $(SMBDOBJ) +smbd: server.o newlinelib.o $(SMBDOBJ) @echo Linking smbd - @$(CC) $(CFLAGS) -o smbd server.o $(SMBDOBJ) $(LIBS) $(AFS_LIBS) + @$(CC) $(CFLAGS) -o smbd server.o newlinelib.o $(SMBDOBJ) $(LIBS) $(AFS_LIBS) smbrun: smbrun.o @echo Linking smbrun @$(CC) $(CFLAGS) -o smbrun smbrun.o $(LIBS) diff -U 5 -r -N oldsource/newlinelib.c newsource/newlinelib.c --- oldsource/newlinelib.c Wed Dec 31 19:00:00 1969 +++ newsource/newlinelib.c Wed Dec 2 07:37:13 1998 @@ -0,0 +1,248 @@ +/* + * newlinelib.c + * Used for determining and converting newline formats. + * + * History: + * Developed 970714 for use in creating automatic file format changing in Samba. + * + * Copyright (c) 1997 David R. Harris. All rights reserved. + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + */ + +#include +#include +#include +#include "newlinelib.h" + + +/******************************************************************************/ +/******************************************************************************/ +/* Function to determine a file format */ + +int findFileFormat( + int readFile +) { + int countBigLoop; + int counter = 0; + int numCount = NLL_FFF_FIRSTREAD; + char buff[NLL_BUFFSIZE]; + int buffNextChar = 1; + int buffNumChars = 0; + int numLF = 0; + int numBinary = 0; + int numCRLF = 0; + char thisChar = 0; + char lastChar; + + /* Loop for levels of counting */ + for( countBigLoop = 0 ; countBigLoop <= 1 ; countBigLoop++ ) { + + /* Loop for the characters to read */ + for( ; counter < numCount ; counter++ ) { + + /* Get another buf full of chars if needed */ + if ( buffNextChar >= buffNumChars ) { + + /* Get anothe buf full */ + buffNumChars = read(readFile, buff, (size_t)sizeof(buff)); + buffNextChar = 0; + + /* Handle a possible EOF */ + if( buffNumChars == 0 ) + break; + } + + /* Get the character */ + lastChar = thisChar; + thisChar = buff[buffNextChar++]; + + /* Do the counting */ + if( (int)(unsigned char)thisChar == 10 ) + numLF++; + if( (int)(unsigned char)thisChar == 10 && lastChar == 13 ) + numCRLF++; + if( ( (int)(unsigned char)thisChar <= 31 && + (int)(unsigned char)thisChar != 13 && + (int)(unsigned char)thisChar != 10 ) || + ( (int)(unsigned char)thisChar >= 128 ) ) + numBinary++; + } + + /* If for two ways to decide, can defer or can't */ + if ( countBigLoop == 0 && buffNumChars != 0 ) { + + /* Determine what type of file this is */ + if ( numBinary >= (int)( (float)(counter + 1) * 0.30 ) ) + return BINARY; + if ( numBinary <= (int)( (float)(counter + 1) * 0.10 ) ) { + if ( (numLF - numCRLF) >= ( numCRLF * 2 ) ) + return ASCII_UNIX; + if ( numCRLF >= ( (numLF - numCRLF) * 2 ) ) + return ASCII_DOS; + } + + /* Can't defer descision */ + } else { + + /* Determine what type of file this is */ + if ( numBinary >= (int)( (float)(counter + 1) * 0.15 ) ) + return BINARY; + if ( (numLF - numCRLF) >= numCRLF ) { + return ASCII_UNIX; + } else { + return ASCII_DOS; + } + } + + /* Looks like we defered the descision, count some more */ + numCount = NLL_FFF_SECONDREAD; + } +} + +/******************************************************************************/ +/******************************************************************************/ +/* Function to convert UNIX files into DOS files */ + +int convertUnixToDos( + int readFile, + int writeFile +) { + char buff[NLL_BUFFSIZE]; + int buffThisChar = 0; + int buffNumChars = 0; + int buffBeginNextWrite = 1; + + /* Loop for chunks */ + while ( 1 ) { + + /* Get another buf full of chars if needed */ + if ( buffThisChar >= buffNumChars ) { + + /* Write the last part of the current buff */ + write(writeFile, buff + buffBeginNextWrite, (size_t) + (buffThisChar - buffBeginNextWrite)); + + /* Go get a new buff of chars */ + buffNumChars = read(readFile, buff, (size_t)sizeof(buff)); + buffThisChar = 0; + buffBeginNextWrite = 0; + + /* Handle an EOF */ + if( buffNumChars == 0 ) + break; + } + + /* If we found a LF */ + if ( (int)(unsigned char)buff[buffThisChar] == 10 ) { + + /* Print the last buff with a CR */ + buff[buffThisChar] = (char)(unsigned char)13; + write(writeFile, buff + buffBeginNextWrite, (size_t) + (buffThisChar - buffBeginNextWrite + 1)); + buffBeginNextWrite = buffThisChar; + + /* Set up the next write to print the LF */ + buff[buffThisChar] = (char)(unsigned char)10; + } + + /* Move on to the next char */ + buffThisChar++; + } + + return 0; +} + +/******************************************************************************/ +/******************************************************************************/ +/* Function to convert DOS files into UNIX files */ + +/* + * Actually, this just removes all CR's instead of converting all CRLF's into + * CR's. Therefor, if there is a lone CR around it will get deleted. I don't + * really feel that this is a bug, because lone CR's are a mistake. + * - David Harris 7/17/97 + */ + +int convertDosToUnix( + int readFile, + int writeFile +) { + char buff[NLL_BUFFSIZE]; + int buffThisChar = 0; + int buffNumChars = 0; + int buffBeginNextWrite = 1; + + /* Loop for chunks */ + while ( 1 ) { + + /* Get another buf full of chars if needed */ + if ( buffThisChar >= buffNumChars ) { + + /* Write the last part of the current buff */ + write(writeFile, buff + buffBeginNextWrite, (size_t) + (buffThisChar - buffBeginNextWrite)); + + /* Go get a new buff of chars */ + buffNumChars = read(readFile, buff, (size_t)sizeof(buff)); + buffThisChar = 0; + buffBeginNextWrite = 0; + + /* Handle an EOF */ + if( buffNumChars == 0 ) + break; + } + + /* If we found a CR */ + if ( (int)(unsigned char)buff[buffThisChar] == 13 ) { + + /* Print the last buff without the CR */ + write(writeFile, buff + buffBeginNextWrite, (size_t) + (buffThisChar - buffBeginNextWrite)); + buffBeginNextWrite = buffThisChar + 1; + } + + /* Move on to the next char */ + buffThisChar++; + } + + return 0; +} + +/******************************************************************************/ +/******************************************************************************/ +/* Don't convert, just copy */ + +int convertNone( + int readFile, + int writeFile +) { + char buff[NLL_BUFFSIZE]; + int buffNumChars = 0; + + /* Loop for chunks */ + while ( 1 ) { + + /* Go get a new buff of chars */ + buffNumChars = read(readFile, buff, (size_t)sizeof(buff)); + + /* Handle an EOF */ + if( buffNumChars == 0 ) { + break; + } + + /* Write out the current buff */ + write(writeFile, buff, (size_t)buffNumChars); + } + + return 0; +} diff -U 5 -r -N oldsource/newlinelib.h newsource/newlinelib.h --- oldsource/newlinelib.h Wed Dec 31 19:00:00 1969 +++ newsource/newlinelib.h Wed Dec 2 07:36:41 1998 @@ -0,0 +1,61 @@ +/* + * newlinelib.c + * Used for determining and converting newline formats. + * + * History: + * Developed 970714 for use in creating automatic file format changing in Samba. + * + * Copyright (c) 1997 David R. Harris. All rights reserved. + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + */ + +/******************************************************************************/ +/******************************************************************************/ +/* Some defines for this library */ + +/* The size of the read buffer */ +#define NLL_BUFFSIZE 500 + +/* The amount of charactes to read in for determining the size of a file */ +#define NLL_FFF_FIRSTREAD 300 +#define NLL_FFF_SECONDREAD 3000 + +/******************************************************************************/ +/******************************************************************************/ +/* Enum for the newline/file formats */ + +enum fileFormat {BINARY = 1, ASCII_UNIX, ASCII_DOS}; + +/******************************************************************************/ +/******************************************************************************/ +/* Functions */ + +int findFileFormat( + int readFile +); + +int convertUnixToDos( + int readFile, + int writeFile +); + +int convertDosToUnix( + int readFile, + int writeFile +); + +int convertNone( + int readFile, + int writeFile +); + diff -U 5 -r -N oldsource/server.c newsource/server.c --- oldsource/server.c Wed Dec 2 07:40:34 1998 +++ newsource/server.c Wed Dec 2 07:37:28 1998 @@ -17,13 +17,42 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + * This program was modified by David R. Harris (DRH) on and slightly + * before the date 7/17/97. The ability to convert between Unix and + * Dos file formats was added. The following modifications were made: + * + * Changes in server.c: + * - Modified the function open_file to become open_file_wrapped + * - Modified the function close_file to become close_file_wrapped + * - Created the function open_file. + * - Created the function open_file. + * - Slightly modified the function write_file. + * + * Changes in smb.h: + * - Added to the structure files_struct. + * + * Changes in Makefile: + * - Added newlinelib.o to the dependencies of server.o. + * + * New files: + * - newlinelib.c to do the newline format translation and detection. + * - newlinelib.h header file for newlinelib.c + */ + + #include "includes.h" #include "trans2.h" +/* Begin added by DRH */ +#include "newlinelib.h" +/* End added by DRH */ + + pstring servicesf = CONFIGFILE; extern pstring debugf; extern pstring sesssetup_user; char *InBuffer = NULL; @@ -920,44 +949,306 @@ } } return fd_ptr->ref_count; } +/********************************************************************/ +/********************************************************************/ +/* give this here because `make proto` is broken... */ + +file_fd_struct* open_file_wrapped (int fnum,int cnum,char *fname1,int flags,int mode, + struct stat *sbuf); + +void close_file_wrapped(int fnum, file_fd_struct* fd_ptr); + /**************************************************************************** open a file ****************************************************************************/ void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf) { + int expected_file_format; + int file_format_type; + + /* Ini some stuff */ + files_struct* this_file = Files + fnum; + int tmp_file_flags = ( flags & ~(O_RDONLY | O_WRONLY | O_EXCL) ) | + ( O_RDWR | O_CREAT ); + +DEBUG(3,("open_file ----- just called with: fnum = %d; cnum = %d; fname1 = %s\n", fnum, cnum, fname1)); +DEBUG(3,("open_file ----- flags: O_RDONLY = %d; O_WRONLY = %d; O_RDWR = %d\n", (flags & O_RDONLY), (flags & O_WRONLY), (flags & O_RDWR))); + + /* Sometimes, becuase of a bug we get called without any flags! */ + if ( ( flags & (O_RDONLY|O_WRONLY|O_RDWR) ) == 0 ) { + flags |= O_RDWR; + } + +DEBUG(3,("open_file ----- revised flags: O_RDONLY = %d; O_WRONLY = %d; O_RDWR = %d\n", (flags & O_RDONLY), (flags & O_WRONLY), (flags & O_RDWR))); + + +DEBUG(3,("open_file ----- Got to B\n")); + + /* If this is a printer, handle it and return */ + if ( Connections[cnum].printer ) { + open_file_wrapped(fnum, cnum, fname1, flags, mode, sbuf); + return; +DEBUG(3,("open_file ----- Got to B.3\n")); + } + +DEBUG(3,("open_file ----- Got to C\n")); + + /* Get a temp file name, even though we may not use it */ + tmpnam(this_file->tmp_file_name); + +DEBUG(3,("open_file ----- tmp_file_name = %s\n", this_file->tmp_file_name)); +DEBUG(3,("open_file ----- Got to D\n")); + + /* Set up some other stuff in this_file */ + this_file->open_request_flags = flags; + this_file->have_written = 0; + this_file->hidden_fd_ptr = NULL; + + DEBUG(3,("open_file ----- Got to E\n")); + + /* Determine what type to convert to if file is ASCII */ + expected_file_format = ASCII_DOS; + + DEBUG(3,("open_file ----- Got to F\n")); + + /* We just assumed that the whole world expects DOS file format now. + * Not a good assumption.. but it works for my purposes. Some other + * person could do some smart stuff here. + */ + + /* If we are opening the file for writeing */ + if ( flags & O_WRONLY ) { + +DEBUG(3,("open_file ----- we are in opening for writeing\n")); + + /* Open the tmpFile in the connectionFile slot */ + open_file_wrapped(fnum, cnum, this_file->tmp_file_name, tmp_file_flags, 0700, NULL); + +DEBUG(3,("open_file ----- just opened the tmpFile in the connectionFile slot\n")); + + /* Open the realFile in the hiddenFile slot */ + this_file->hidden_fd_ptr = + open_file_wrapped(-1, -1, fname1, flags, mode, sbuf); + +DEBUG(3,("open_file ----- just opened the realFile in the hiddenFile slot\n")); + + /* If we are opening the file for reading ( O_RDONLY or O_RDWR ) */ + } else { + +DEBUG(3,("open_file ----- we are in opening for reading\n")); + + /* Open the realFile in the connectionFile slot */ + open_file_wrapped(fnum, cnum, fname1, flags, mode, sbuf); + +DEBUG(3,("open_file ----- just opened the realFile in the connectionFile slot\n")); + + /* Determine the type of the realFile */ + seek_file(fnum, 0); + file_format_type = findFileFormat(this_file->fd_ptr->fd); + seek_file(fnum, 0); + +DEBUG(3,("open_file ----- Just determine the type of the realFile\n")); +DEBUG(3,("open_file ----- file_format_type = %d\n", file_format_type)); + + /* If we don't need to create a new file ( format OK and no O_RDWR ) */ + if ( ( ( file_format_type == expected_file_format ) || + ( file_format_type == BINARY ) ) && !(flags & O_RDWR) ) { + +DEBUG(3,("open_file ----- Don't need to create a tmpFile\n")); + + /* Just say that we did not open another file */ + this_file->hidden_fd_ptr = NULL; + + /* If we do need to use a tmpFile */ + } else { + +DEBUG(3,("open_file ----- Do need to create a tmpFile\n")); + + /* Open the realFile in the hiddenFile slot */ + this_file->hidden_fd_ptr = + open_file_wrapped(-1, -1, fname1, flags, mode, sbuf); + +DEBUG(3,("open_file ----- just opened the realFile in the hiddenFile slot\n")); + + /* Close the realFile in the connectionFile slot */ + close_file_wrapped(fnum, this_file->fd_ptr); + +DEBUG(3,("open_file ----- just closed the realFile in the connectionFile slot\n")); + + /* Open the tmpFile in the connectionFile slot */ + open_file_wrapped(fnum, cnum, this_file->tmp_file_name, + tmp_file_flags, 0700, NULL); + +DEBUG(3,("open_file ----- Just opened the tmpFile in the connectionFile slot\n")); + + /* Copy from the hiddenFile to the connectionFile */ + seek_file(fnum, 0); + lseek(this_file->hidden_fd_ptr->fd, (off_t) 0, SEEK_SET); + if ( (file_format_type == ASCII_UNIX) && + (expected_file_format == ASCII_DOS) ) { + convertUnixToDos(this_file->hidden_fd_ptr->fd, this_file->fd_ptr->fd); + } else if ( (file_format_type == ASCII_DOS) && + (expected_file_format == ASCII_UNIX) ) { + convertDosToUnix(this_file->hidden_fd_ptr->fd, this_file->fd_ptr->fd); + } else { + convertNone(this_file->hidden_fd_ptr->fd, this_file->fd_ptr->fd); + } + seek_file(fnum, 0); +DEBUG(3,("open_file ----- Just copied from the hiddenFile to the connectionFile\n")); + + } + } + DEBUG(3,("open_file ----- Got to G\n")); +} + +/**************************************************************************** +close a file - possibly invalidating the read prediction +****************************************************************************/ + +void close_file(int fnum) { + files_struct* this_file = Files + fnum; + int file_format_type; + int local_file_format = ASCII_UNIX; + +DEBUG(3,("close_file ----- just called with: fnum = %d\n", fnum)); +DEBUG(3,("close_file ----- this_file->have_written = %d\n", this_file->have_written)); + + /* + * I don't know if the above local_file_format should be configurable. + * Samba says that it is for UNIX, so we might be able to assume this. + * + */ + + /* If this is a printer, handle it and return */ + if ( Connections[this_file->cnum].printer ) { +DEBUG(3,("close_file ----- handleing a printer\n")); + close_file_wrapped(fnum, this_file->fd_ptr); + return; + } + + /* If something was written and we have a hiddenFile */ + if ( ( (this_file->open_request_flags & O_WRONLY) || + ( (this_file->open_request_flags & O_RDWR) && this_file->have_written ) ) && + (this_file->hidden_fd_ptr != NULL) ) { + +DEBUG(3,("close_file ----- Something was written, hiden file exists.\n")); + + /* Determine the connectionFile type */ + seek_file(fnum, 0); + file_format_type = findFileFormat(this_file->fd_ptr->fd); + seek_file(fnum, 0); + +DEBUG(3,("close_file ----- just determined the connectionFile type\n")); +DEBUG(3,("close_file ----- file_format_type = %d\n", file_format_type)); + + /* Truncate the hidden file */ + ftruncate(this_file->hidden_fd_ptr->fd, 0); + +DEBUG(3,("close_file ----- just truncated the file.\n")); + + /* Copy from the connectionFile to the hiddenFile */ + lseek(this_file->hidden_fd_ptr->fd, (off_t) 0, SEEK_SET); + seek_file(fnum, 0); + if ( (file_format_type == ASCII_UNIX) && + (local_file_format == ASCII_DOS) ) { + convertUnixToDos(this_file->fd_ptr->fd, this_file->hidden_fd_ptr->fd); + } else if ( (file_format_type == ASCII_DOS) && + (local_file_format == ASCII_UNIX) ) { + convertDosToUnix(this_file->fd_ptr->fd, this_file->hidden_fd_ptr->fd); + } else { + convertNone(this_file->fd_ptr->fd, this_file->hidden_fd_ptr->fd); + } + seek_file(fnum, 0); +DEBUG(3,("close_file ----- just copied from the connectionFile to the hiddenFile\n")); + } + + /* If we have a hiddenFile */ + if ( this_file->hidden_fd_ptr != NULL ) { + +DEBUG(3,("close_file ----- we have a hidden file to close\n")); + + /* Close the hiddenFile */ + close_file_wrapped(-1, this_file->hidden_fd_ptr); + +DEBUG(3,("close_file ----- just closed the hidden file\n")); + } + + /* Close the connectionFile */ + close_file_wrapped(fnum, this_file->fd_ptr); + +DEBUG(3,("close_file ----- just closed the connection file\n")); + + /* If we had a tmpFile */ + if ( this_file->hidden_fd_ptr != NULL ) { +DEBUG(3,("close_file ----- we have a demp file to delete\n")); + /* Delete the tmpFile */ + unlink(this_file->tmp_file_name); +DEBUG(3,("close_file ----- just deleted the tmp file\n")); + + } +} + +/********************************************************************/ +/********************************************************************/ +/* + * open_file_wrapped + * Does all of the same stuff as open_file. If fnum or cnum == -1 then + * it does not do any of the connection specific stuff. + * + * Returns a NULL on error and a file_fd_struct* on success. If there is no + * associated connection then this return value is usefull. + */ + +file_fd_struct* open_file_wrapped (int fnum,int cnum,char *fname1,int flags,int mode, + struct stat *sbuf) +{ extern struct current_user current_user; pstring fname; struct stat statbuf; file_fd_struct *fd_ptr; + int haveConnection = (fnum != -1) && (cnum != -1); + +DEBUG(3,("open_file_wrapped ----- haveConnection = %d; fnum = %d; cnum = %d\n", + haveConnection, fnum, cnum)); + + /* Connection conditional stuff */ + if ( haveConnection ) { + Files[fnum].open = False; + Files[fnum].fd_ptr = 0; + } - Files[fnum].open = False; - Files[fnum].fd_ptr = 0; errno = EPERM; strcpy(fname,fname1); - /* check permissions */ - if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer) - { - DEBUG(3,("Permission denied opening %s\n",fname)); - check_for_pipe(fname); - return; - } + /* Connection conditional stuff */ + if ( haveConnection ) { - /* this handles a bug in Win95 - it doesn't say to create the file when it - should */ - if (Connections[cnum].printer) - flags |= O_CREAT; + /* check permissions */ + if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer) + { + DEBUG(3,("Permission denied opening %s\n",fname)); + check_for_pipe(fname); + return; + } + + /* this handles a bug in Win95 - it doesn't say to create the file when it + should */ + if (Connections[cnum].printer) + flags |= O_CREAT; /* - if (flags == O_WRONLY) - DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n")); + if (flags == O_WRONLY) + DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n")); */ + } + +/* I am not sure if this is connection conditional stuff. I don't think it is. */ #if UTIME_WORKAROUND /* XXXX - is this OK?? */ /* this works around a utime bug but can cause other problems */ if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND)) sys_unlink(fname); @@ -972,11 +1263,11 @@ if(errno != ENOENT) { DEBUG(3,("Error doing stat on file %s (%s)\n", fname,strerror(errno))); check_for_pipe(fname); - return; + return NULL; } sbuf = 0; } else { sbuf = &statbuf; } @@ -993,11 +1284,11 @@ /* File was already open. */ if((flags & O_CREAT) && (flags & O_EXCL)) { fd_ptr->ref_count--; errno = EEXIST; - return; + return NULL; } /* * If not opened O_RDWR try * and do that here - a chmod may have been done @@ -1016,11 +1307,11 @@ ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) { DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n", fd_ptr->real_open_flags, fname,strerror(EACCES),flags)); check_for_pipe(fname); fd_ptr->ref_count--; - return; + return NULL; } /* * If O_TRUNC was set, ensure we truncate the file. * open_file_shared explicitly clears this flag before @@ -1032,11 +1323,11 @@ } else { int open_flags; /* We need to allocate a new file_fd_struct (this increments the ref_count). */ if((fd_ptr = fd_get_new()) == 0) - return; + return NULL; /* * Whatever the requested flags, attempt read/write access, * as we don't know what flags future file opens may require. * If this fails, try again with the required flags. * Even if we open read/write when only read access was @@ -1066,37 +1357,41 @@ fd_ptr->real_open_flags = O_RDONLY; } } } - if ((fd_ptr->fd >=0) && - Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) { - pstring dname; - int dum1,dum2,dum3; - char *p; - strcpy(dname,fname); - p = strrchr(dname,'/'); - if (p) *p = 0; - if (sys_disk_free(dname,&dum1,&dum2,&dum3) < - lp_minprintspace(SNUM(cnum))) { - fd_attempt_close(fd_ptr); - Files[fnum].fd_ptr = 0; - if(fd_ptr->ref_count == 0) - sys_unlink(fname); - errno = ENOSPC; - return; + /* Connection conditional stuff */ + if ( haveConnection ) { + + if ((fd_ptr->fd >=0) && + Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) { + pstring dname; + int dum1,dum2,dum3; + char *p; + strcpy(dname,fname); + p = strrchr(dname,'/'); + if (p) *p = 0; + if (sys_disk_free(dname,&dum1,&dum2,&dum3) < + lp_minprintspace(SNUM(cnum))) { + fd_attempt_close(fd_ptr); + Files[fnum].fd_ptr = 0; + if(fd_ptr->ref_count == 0) + sys_unlink(fname); + errno = ENOSPC; + return NULL; + } } } if (fd_ptr->fd < 0) { DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", fname,strerror(errno),flags)); /* Ensure the ref_count is decremented. */ fd_attempt_close(fd_ptr); check_for_pipe(fname); - return; + return NULL; } if (fd_ptr->fd >= 0) { if(sbuf == 0) { @@ -1105,75 +1400,88 @@ /* Error - backout !! */ DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n", fd_ptr->fd, fname,strerror(errno))); /* Ensure the ref_count is decremented. */ fd_attempt_close(fd_ptr); - return; + return NULL; } sbuf = &statbuf; } /* Set the correct entries in fd_ptr. */ fd_ptr->dev = (int32)sbuf->st_dev; fd_ptr->inode = (int32)sbuf->st_ino; - Files[fnum].fd_ptr = fd_ptr; - Connections[cnum].num_files_open++; - Files[fnum].mode = sbuf->st_mode; - GetTimeOfDay(&Files[fnum].open_time); - Files[fnum].uid = current_user.id; - Files[fnum].size = 0; - Files[fnum].pos = -1; - Files[fnum].open = True; - Files[fnum].mmap_ptr = NULL; - Files[fnum].mmap_size = 0; - Files[fnum].can_lock = True; - Files[fnum].can_read = ((flags & O_WRONLY)==0); - Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0); - Files[fnum].share_mode = 0; - Files[fnum].share_pending = False; - Files[fnum].print_file = Connections[cnum].printer; - Files[fnum].modified = False; - Files[fnum].cnum = cnum; - string_set(&Files[fnum].name,dos_to_unix(fname,False)); - Files[fnum].wbmpx_ptr = NULL; - - /* - * If the printer is marked as postscript output a leading - * file identifier to ensure the file is treated as a raw - * postscript file. - * This has a similar effect as CtrlD=0 in WIN.INI file. - * tim@fsg.com 09/06/94 - */ - if (Files[fnum].print_file && POSTSCRIPT(cnum) && - Files[fnum].can_write) - { - DEBUG(3,("Writing postscript line\n")); - write_file(fnum,"%!\n",3); - } - - DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", - timestring(),Connections[cnum].user,fname, - BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write), - Connections[cnum].num_files_open,fnum)); + /* Connection conditional stuff */ + if ( haveConnection ) { + Files[fnum].fd_ptr = fd_ptr; + Connections[cnum].num_files_open++; + Files[fnum].mode = sbuf->st_mode; + GetTimeOfDay(&Files[fnum].open_time); + Files[fnum].uid = current_user.id; + Files[fnum].size = 0; + Files[fnum].pos = -1; + Files[fnum].open = True; + Files[fnum].mmap_ptr = NULL; + Files[fnum].mmap_size = 0; + Files[fnum].can_lock = True; + Files[fnum].can_read = ((flags & O_WRONLY)==0); + Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0); + Files[fnum].share_mode = 0; + Files[fnum].share_pending = False; + Files[fnum].print_file = Connections[cnum].printer; + Files[fnum].modified = False; + Files[fnum].cnum = cnum; + string_set(&Files[fnum].name,dos_to_unix(fname,False)); + Files[fnum].wbmpx_ptr = NULL; + + /* + * If the printer is marked as postscript output a leading + * file identifier to ensure the file is treated as a raw + * postscript file. + * This has a similar effect as CtrlD=0 in WIN.INI file. + * tim@fsg.com 09/06/94 + */ + if (Files[fnum].print_file && POSTSCRIPT(cnum) && + Files[fnum].can_write) + { + DEBUG(3,("Writing postscript line\n")); + write_file(fnum,"%!\n",3); + } + + DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", + timestring(),Connections[cnum].user,fname, + BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write), + Connections[cnum].num_files_open,fnum)); + + } } #if USE_MMAP - /* mmap it if read-only */ - if (!Files[fnum].can_write) + /* Connection conditional stuff */ + if ( haveConnection ) { + + /* mmap it if read-only */ + if (!Files[fnum].can_write) { Files[fnum].mmap_size = file_size(fname); Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size, - PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0); + PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0); if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr) { DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno))); Files[fnum].mmap_ptr = NULL; } } + } #endif + +DEBUG(3,("open_file_wrapped ----- Got to Z\n")); + + /* Return the success value */ + return fd_ptr; } /******************************************************************* sync a file ********************************************************************/ @@ -1222,24 +1530,44 @@ unlink(fname); } } -/**************************************************************************** -close a file - possibly invalidating the read prediction -****************************************************************************/ -void close_file(int fnum) +/********************************************************************/ +/********************************************************************/ +/* + * close_file_wrapped + * Does all of the same stuff as open_file. If fnum == -1 then + * it does not do any of the connection specific stuff. Must be + * given the fild_fd_stuct* fd_ptr from the Files array to work. + * + */ +/********************************************************************/ +/********************************************************************/ + + +void close_file_wrapped(int fnum, file_fd_struct* fd_ptr) { - int cnum = Files[fnum].cnum; - invalidate_read_prediction(Files[fnum].fd_ptr->fd); - Files[fnum].open = False; - Connections[cnum].num_files_open--; - if(Files[fnum].wbmpx_ptr) - { - free((char *)Files[fnum].wbmpx_ptr); - Files[fnum].wbmpx_ptr = NULL; - } + int haveConnection = fnum != -1; + int cnum; + + /* Connection only stuff */ + if ( haveConnection ) { + cnum = Files[fnum].cnum; + } + + invalidate_read_prediction(fd_ptr->fd); + + /* Connection only stuff */ + if ( haveConnection ) { + Files[fnum].open = False; + Connections[cnum].num_files_open--; + if(Files[fnum].wbmpx_ptr) + { + free((char *)Files[fnum].wbmpx_ptr); + Files[fnum].wbmpx_ptr = NULL; + } #if USE_MMAP if(Files[fnum].mmap_ptr) { munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size); @@ -1247,23 +1575,34 @@ } #endif if (lp_share_modes(SNUM(cnum))) del_share_mode(fnum); + } + + fd_attempt_close(fd_ptr); - fd_attempt_close(Files[fnum].fd_ptr); + /* Connection only stuff */ + if ( haveConnection ) { - /* NT uses smbclose to start a print - weird */ - if (Files[fnum].print_file) - print_file(fnum); - - /* check for magic scripts */ - check_magic(fnum,cnum); - - DEBUG(2,("%s %s closed file %s (numopen=%d)\n", - timestring(),Connections[cnum].user,Files[fnum].name, - Connections[cnum].num_files_open)); + /* NT uses smbclose to start a print - weird */ + if (Files[fnum].print_file) + print_file(fnum); + + /* check for magic scripts */ + check_magic(fnum,cnum); + + DEBUG(2,("%s %s closed file (with connection) %s (numopen=%d)\n", + timestring(),Connections[cnum].user,Files[fnum].name, + Connections[cnum].num_files_open)); + + /* If we don't have a connection */ + } else { + + DEBUG(2,("Closed file without connection.\n")); + + } } enum {AFAIL,AREAD,AWRITE,AALL}; /******************************************************************* @@ -1611,10 +1950,13 @@ { if (!Files[fnum].can_write) { errno = EPERM; return(0); } + + /* Added by DRH for use in CRLF <-> LF conversion */ + Files[fnum].have_written = 1; if (!Files[fnum].modified) { struct stat st; Files[fnum].modified = True; if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) { diff -U 5 -r -N oldsource/smb.h newsource/smb.h --- oldsource/smb.h Wed Dec 2 07:39:55 1998 +++ newsource/smb.h Wed Dec 2 07:36:43 1998 @@ -16,10 +16,35 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + * This program was modified by David R. Harris (DRH) on and slightly + * before the date 7/17/97. The ability to convert between Unix and + * Dos file formats was added. The following modifications were made: + * + * Changes in server.c: + * - Modified the function open_file to become open_file_wrapped + * - Modified the function close_file to become close_file_wrapped + * - Created the function open_file. + * - Created the function open_file. + * - Slightly modified the function write_file. + * + * Changes in smb.h: + * - Added to the structure files_struct. + * + * Changes in Makefile: + * - Added newlinelib.o to the dependencies of server.o. + * + * New files: + * - newlinelib.c to do the newline format translation and detection. + * - newlinelib.h header file for newlinelib.c + */ + + #ifndef _SMB_H #define _SMB_H #ifndef MAX_CONNECTIONS #define MAX_CONNECTIONS 127 @@ -322,10 +347,16 @@ BOOL share_mode; BOOL share_pending; BOOL print_file; BOOL modified; char *name; +/* DRH: Begin added stuff */ + char tmp_file_name[L_tmpnam]; + file_fd_struct *hidden_fd_ptr; + int open_request_flags; + BOOL have_written; +/* DRH: End added stuff */ } files_struct; struct uid_cache { int entries;