Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Examples  

flock.c

Go to the documentation of this file.
00001 /*! \file flock.c
00002     This file contains funtions used to lock/unlock files.
00003  */
00004 
00005 #include "flock.h"
00006 #include <stdio.h>
00007 
00008 #define DEBUG_TRACE(x) fprintf (stderr, x)
00009 
00010 /*! \brief Lock a file.
00011     \param fd File descriptor that identifies the file to lock.
00012     \return If the lock succed, the function returns 0. Otherwise the function returns 1.
00013  */
00014 
00015 int lock_file(int fd)
00016 {
00017   int cr;
00018 
00019   #ifdef SUN
00020     struct flock lck;
00021   #endif
00022 
00023   #ifdef LINUX
00024     cr = flock (fd, LOCK_EX);
00025     if (cr == -1)
00026     {
00027       DEBUG_TRACE("\n\nflock failed\n\n");
00028       return 1;
00029     }
00030   #endif
00031 
00032   #ifdef SUN
00033     lck.l_start   = 0;        /* from the beginning of thr file ... */
00034     lck.l_len     = 0;        /* to the end if the file.            */
00035     lck.l_type    = F_WRLCK;  /* exclusive lock                     */
00036     lck.l_whence  = SEEK_SET; /* lock from the beginning            */
00037     cr = fcntl (fd, F_SETLKW, &lck);
00038     if (cr == -1)
00039     {
00040       DEBUG_TRACE("\n\nfcntl failed\n\n");
00041       return 1;
00042     }
00043   #endif
00044 
00045   return 0;
00046 }
00047 
00048 /*! \brief Unlock a file.
00049     \param fd File descriptor that identifies the file to unlock.
00050     \return If the operation succed, the function returns 0. Otherwise the function returns 1.
00051  */
00052 
00053 int unlock_file(int fd)
00054 {
00055   int cr;
00056 
00057   #ifdef SUN
00058     struct flock lck;
00059   #endif
00060 
00061   #ifdef LINUX
00062     cr = flock (fd, LOCK_UN);
00063     if (cr == -1)
00064     {
00065       DEBUG_TRACE("\n\nflock failed\n\n");
00066       return 1;
00067     }
00068   #endif
00069 
00070   #ifdef SUN
00071     lck.l_start   = 0;        /* from the beginning of thr file ... */
00072     lck.l_len     = 0;        /* to the end if the file.            */
00073     lck.l_type    = F_UNLCK;  /* exclusive lock                     */
00074     lck.l_whence  = SEEK_SET; /* lock from the beginning            */
00075     cr = fcntl (fd, F_SETLKW, &lck);
00076     if (cr == -1)
00077     {
00078       DEBUG_TRACE("\n\nfcntl failed\n\n");
00079       return 1;
00080     }
00081   #endif
00082 
00083   return 0;
00084 }
00085 
00086 
00087 /*! \brief Maximum number of characters for an integer.
00088  */
00089 
00090 #define INT_MAX_CHAR    32
00091 
00092 /*! \brief Write data into the log file.
00093     \param file_name Pointer to a NULL terminated string of characters that contains the name of the log file.
00094            Please note that if file_name[0] is equal to 0, then the function does nothing. This may be used to
00095            manage debug logging.
00096     \param buffer Pointer to a memory location used by the function to format the data to print.
00097     \param buffsize Size of the memory location 'buffer' in bytes.
00098     \param format Pointer to a NULL terminated string of characters that describes the format of the output. 's' means
00099            'char*', 'd' means 'interger' and 'u' means 'unsigned int'.
00100     \return The function return LOG_OK if the operation succed. Otherwise the function returns LOG_BUFFER_OVERFLOW,
00101             LOG_WRITE_ERROR, LOG_OPEN_ERROR, LOG_CLOSE_ERROR or LOG_LOCK_ERROR.
00102  */
00103 
00104 
00105 int my_logger (char *file_name, char *buffer, int buffsize, char *format, ...)
00106 {
00107    int          flock_fd;
00108    int          cr;
00109    int          done;
00110    char         buff[INT_MAX_CHAR];
00111 
00112    va_list      ap;
00113    char         *s;
00114    int          d;
00115    unsigned int u;
00116   
00117 
00118    /*****************************/
00119    /* If the name of the file   */
00120    /* empty, then do nothing.   */
00121    /*****************************/
00122 
00123    if (file_name[0] == 0) { return LOG_OK; }
00124  
00125    /*****************************/
00126    /* Open and lock the file    */
00127    /*****************************/
00128 
00129    flock_fd = open (file_name, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
00130    if (flock_fd == -1)
00131    {
00132      DEBUG_TRACE("\n\nopen failed\n\n");
00133      return LOG_OPEN_ERROR;
00134    }
00135 
00136    cr = lock_file (flock_fd);
00137    if (cr == 1)
00138    {
00139      DEBUG_TRACE("\n\nlock_file failed\n\n");
00140      close(flock_fd); return LOG_LOCK_ERROR;
00141    }
00142 
00143    /*****************************/
00144    /* Extract stuff to write    */
00145    /*****************************/
00146 
00147    va_start (ap, format);
00148    done      = 0;
00149    memset ((void*)buffer, 0, buffsize);
00150 
00151    while (*format)
00152    {
00153      switch  (*(format++))
00154      {
00155        case 's': {
00156             s = va_arg (ap, char *);
00157             if (s != NULL)
00158             {
00159               done += strlen(s);
00160               if (done > buffsize-1)
00161               {
00162                 unlock_file (flock_fd);
00163                 close (flock_fd);
00164                 return LOG_BUFFER_OVERFLOW;
00165               }
00166               strcat (buffer, s);
00167             }
00168        }; break;
00169 
00170        case 'd': {
00171             d = va_arg (ap, int);
00172             sprintf (buff, "%d", d);
00173             done += strlen(buff);
00174             if (done > buffsize-1)
00175             {
00176               unlock_file (flock_fd);
00177               close (flock_fd);
00178               return LOG_BUFFER_OVERFLOW;
00179             }
00180             strcat (buffer, buff);
00181        }; break;
00182 
00183        case 'u': {
00184             u = va_arg (ap, unsigned int);
00185             sprintf (buff, "%u", u);
00186             done += strlen(buff);
00187             if (done > buffsize-1)
00188             {
00189               unlock_file (flock_fd);
00190               close (flock_fd);
00191               return LOG_BUFFER_OVERFLOW;
00192             }
00193             strcat (buffer, buff);
00194        }; break;
00195      }
00196    }
00197 
00198    /*****************************/
00199    /* Write data to log file    */
00200    /*****************************/
00201 
00202    cr = write (flock_fd, buffer, strlen(buffer));
00203    if (cr == -1)
00204    {
00205       unlock_file (flock_fd);
00206       close (flock_fd);
00207       return LOG_WRITE_ERROR;
00208    }
00209 
00210    /*****************************/
00211    /* Unlock and close the file */
00212    /*****************************/
00213 
00214    cr = unlock_file (flock_fd);
00215    if (cr == 1)
00216    {
00217      DEBUG_TRACE("\n\nunlock_file failed\n\n");
00218      close(flock_fd); return LOG_LOCK_ERROR;
00219    }
00220 
00221    cr = close (flock_fd);
00222    if (cr == -1)
00223    {
00224      DEBUG_TRACE("\n\nclose failed\n\n");
00225      return LOG_CLOSE_ERROR;
00226    }
00227 
00228    return LOG_OK;
00229 }
00230 
00231 /*! \example test_flock.c
00232     This file shows how to ise the function my_logger().
00233  */
00234 
00235 
00236 /*! \brief Append a file to another - The destination file is locked.
00237     \param src Pointer to a zero terminated string of characters that represents the name of the source file.
00238     \param dst Pointer to a zero terminated string of characters that represents the name of the destination file.
00239     \return The function returns COPY_OK if the operation succed. Otherwise, the function may return:
00240             <UL>
00241               <li>COPY_SRC_OPEN_ERROR Can not open the source file.
00242               <li>COPY_DST_OPEN_ERROR Can not open the destination file.
00243               <li>COPY_LOCK_ERROR Lock on the destination file failed.
00244               <li>COPY_STAT_ERROR Can not stat() the srouce file.
00245               <li>COPY_READ_ERROR Error while reading the source file.
00246               <li>COPY_WRITE_ERROR Error while writing to the destination file.
00247               <li>COPY_UNLOCK_ERROR Error while unlocking the destinatination file.
00248               <li>COPY_SRC_CLOSE_ERROR Error while closing the source file.
00249               <li>COPY_DST_CLOSE_ERROR Error while closing the destination file.
00250             </UL>
00251  */
00252 
00253 int append_file_with_lock (char *src, char *dst)
00254 {
00255    int         src_fd, dst_fd;
00256    int         cr;
00257    off_t       fsize, i, nb_blcoks, reminder;
00258    char        iobuff[COPY_IOBUFF_SIZE];
00259    struct stat s_stat;
00260    size_t      rw;
00261 
00262 
00263    /**********************************/
00264    /* Open the source file           */
00265    /**********************************/
00266   
00267    src_fd = open (src, O_RDONLY, S_IRWXU);
00268    if (src_fd == -1)
00269    {
00270      return COPY_SRC_OPEN_ERROR;
00271    }
00272 
00273    /**********************************/
00274    /* Open the destination file and  */
00275    /* lock it.                       */
00276    /**********************************/
00277 
00278    dst_fd = open (dst, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
00279    if (dst_fd == -1)
00280    {
00281      close (src_fd);
00282      return COPY_DST_OPEN_ERROR;
00283    }
00284 
00285    cr = lock_file (dst_fd);
00286    if (cr == 1)
00287    {
00288      close(src_fd);
00289      close(dst_fd);
00290      return COPY_LOCK_ERROR;
00291    }
00292 
00293    /**********************************/
00294    /* Get file's size                */
00295    /**********************************/
00296 
00297    cr = stat (src, &s_stat);
00298    if (cr != 0)
00299    {
00300      close(src_fd);
00301      unlock_file (dst_fd);
00302      close(dst_fd);
00303      return COPY_STAT_ERROR;
00304    }
00305 
00306    /**********************************/
00307    /* Calculate number of full       */
00308    /* block.                         */
00309    /**********************************/
00310 
00311    fsize = s_stat.st_size;
00312    nb_blcoks = fsize / COPY_IOBUFF_SIZE;
00313    reminder = fsize - (nb_blcoks*COPY_IOBUFF_SIZE);
00314 
00315    /**********************************/
00316    /* Copy full blocks               */
00317    /**********************************/
00318 
00319    for (i=0; i<nb_blcoks; i++)
00320    {
00321      rw = read (src_fd, (void*)iobuff, COPY_IOBUFF_SIZE);
00322      if (rw != COPY_IOBUFF_SIZE)
00323      {
00324        close(src_fd);
00325        unlock_file (dst_fd);
00326        close(dst_fd);
00327        return COPY_READ_ERROR;
00328      }
00329 
00330      rw = write (dst_fd, (void*)iobuff, COPY_IOBUFF_SIZE);
00331      if (rw != COPY_IOBUFF_SIZE)
00332      {
00333        close(src_fd);
00334        unlock_file (dst_fd);
00335        close(dst_fd);
00336        return COPY_WRITE_ERROR;
00337      }
00338    }
00339 
00340    /**********************************/
00341    /* Copy reminder                  */
00342    /**********************************/
00343 
00344    rw = read (src_fd, (void*)iobuff, (size_t)reminder);
00345    if (rw != (size_t)reminder)
00346    {
00347      close(src_fd);
00348      unlock_file (dst_fd);
00349      close(dst_fd);
00350      return COPY_READ_ERROR;
00351    }
00352 
00353    rw = write (dst_fd, (void*)iobuff, (size_t)reminder);
00354    if (rw != (size_t)reminder)
00355    {
00356      close(src_fd);
00357      unlock_file (dst_fd);
00358      close(dst_fd);
00359      return COPY_WRITE_ERROR;
00360    }
00361 
00362    /**********************************/
00363    /* Unlock destination file        */
00364    /**********************************/
00365 
00366    cr = unlock_file (dst_fd);
00367    if (cr == 1)
00368    {
00369      close(src_fd); 
00370      close(dst_fd);
00371      return COPY_UNLOCK_ERROR;
00372    }
00373 
00374    /**********************************/
00375    /* Close all files                */
00376    /**********************************/
00377 
00378    cr = close(src_fd);
00379    if (cr == -1)
00380    {
00381      close(dst_fd);
00382      return COPY_SRC_CLOSE_ERROR;
00383    }
00384 
00385    cr = close(dst_fd);
00386    if (cr == -1)
00387    {
00388      return COPY_DST_CLOSE_ERROR;
00389    }
00390 
00391    return COPY_OK;
00392 }
00393 
00394 /*! \example test_copy_lock.c
00395     This file shows how to use the function append_file_with_lock().
00396  */

Generated on Thu Apr 3 16:23:43 2003 for Common_C_libraries by doxygen1.3-rc1