1    	/****************************************************************************
2    	 *   Copyright (C) 2006-2010 by Jason Ansel, Kapil Arya, and Gene Cooperman *
3    	 *   jansel@csail.mit.edu, kapil@ccs.neu.edu, gene@ccs.neu.edu              *
4    	 *                                                                          *
5    	 *   This file is part of the dmtcp/src module of DMTCP (DMTCP:dmtcp/src).  *
6    	 *                                                                          *
7    	 *  DMTCP:dmtcp/src is free software: you can redistribute it and/or        *
8    	 *  modify it under the terms of the GNU Lesser General Public License as   *
9    	 *  published by the Free Software Foundation, either version 3 of the      *
10   	 *  License, or (at your option) any later version.                         *
11   	 *                                                                          *
12   	 *  DMTCP:dmtcp/src is distributed in the hope that it will be useful,      *
13   	 *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
14   	 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
15   	 *  GNU Lesser General Public License for more details.                     *
16   	 *                                                                          *
17   	 *  You should have received a copy of the GNU Lesser General Public        *
18   	 *  License along with DMTCP:dmtcp/src.  If not, see                        *
19   	 *  <http://www.gnu.org/licenses/>.                                         *
20   	 ****************************************************************************/
21   	
22   	#include <stdlib.h>
23   	#include <string.h>
24   	#include <string>
25   	#include <sstream>
26   	#include <fcntl.h>
27   	#include <errno.h>
28   	#include <sys/syscall.h>
29   	#include "constants.h"
30   	#include  "util.h"
31   	#include  "../jalib/jassert.h"
32   	
33   	void dmtcp::Util::lockFile(int fd)
34   	{
35   	  struct flock fl;
36   	
37   	  fl.l_type   = F_WRLCK;  // F_RDLCK, F_WRLCK, F_UNLCK
38   	  fl.l_whence = SEEK_SET; // SEEK_SET, SEEK_CUR, SEEK_END
39   	  fl.l_start  = 0;        // Offset from l_whence
40   	  fl.l_len    = 0;        // length, 0 = to EOF
41   	  //fl.l_pid    = _real_getpid(); // our PID
42   	
43   	  int result = -1;
44   	  errno = 0;
45   	  while (result == -1 || errno == EINTR)
46   	    result = fcntl(fd, F_SETLKW, &fl);  /* F_GETLK, F_SETLK, F_SETLKW */
47   	
48   	  JASSERT (result != -1) (JASSERT_ERRNO)
49   	    .Text("Unable to lock the PID MAP file");
50   	}
51   	
52   	void dmtcp::Util::unlockFile(int fd)
53   	{
54   	  struct flock fl;
55   	  int result;
56   	  fl.l_type   = F_UNLCK;  // tell it to unlock the region
57   	  fl.l_whence = SEEK_SET; // SEEK_SET, SEEK_CUR, SEEK_END
58   	  fl.l_start  = 0;        // Offset from l_whence
59   	  fl.l_len    = 0;        // length, 0 = to EOF
60   	
61   	  result = fcntl(fd, F_SETLK, &fl); /* set the region to unlocked */
62   	
63   	  JASSERT (result != -1 || errno == ENOLCK) (JASSERT_ERRNO)
64   	    .Text("Unlock Failed");
65   	}
66   	
67   	bool dmtcp::Util::strStartsWith(const char *str, const char *pattern)
68   	{
69   	  int len1 = strlen(str);
70   	  int len2 = strlen(pattern);
71   	  if (len1 >= len2) {
72   	    return strncmp(str, pattern, len2) == 0;
73   	  }
74   	  return false;
75   	}
76   	
77   	bool dmtcp::Util::strEndsWith(const char *str, const char *pattern)
78   	{
79   	  int len1 = strlen(str);
80   	  int len2 = strlen(pattern);
81   	  if (len1 >= len2) {
82   	    size_t idx = len1 - len2;
83   	    return strncmp(str+idx, pattern, len2) == 0;
84   	  }
85   	  return false;
86   	}
87   	
88   	bool dmtcp::Util::strStartsWith(const dmtcp::string& str, const char *pattern)
89   	{
90   	  if (str.length() >= strlen(pattern)) {
91   	    return str.compare(0, strlen(pattern), pattern) == 0;
92   	  }
93   	  return false;
94   	}
95   	
96   	bool dmtcp::Util::strEndsWith(const dmtcp::string& str, const char *pattern)
97   	{
98   	  if (str.length() >= strlen(pattern)) {
99   	    size_t idx = str.length() - strlen(pattern);
100  	    return str.compare(idx, strlen(pattern), pattern) == 0;
101  	  }
102  	  return false;
103  	}
104  	
105  	// Fails or does entire write (returns count)
106  	ssize_t dmtcp::Util::writeAll(int fd, const void *buf, size_t count)
107  	{
108  	  const char *ptr = (const char *) buf;
109  	  ssize_t offs = 0;
110  	
111  	  do {
112  	    ssize_t rc = write (fd, ptr + offs, count - offs);
113  	    if (rc == -1) {
114  	      if (errno == EINTR || errno == EAGAIN) 
115  		continue;
116  	      else
117  	        return rc;
118  	    }
119  	    else if (rc == 0)
120  	      break;
121  	    else // else rc > 0
122  	      offs += rc;
123  	  } while (offs < count);
124  	  JASSERT (offs == count) (offs) (count);
125  	  return count;
126  	}
127  	
128  	// Fails, succeeds, or partial read due to EOF (returns num read)
129  	// return value:
130  	//    -1: unrecoverable error
131  	//   <n>: number of bytes read
132  	ssize_t dmtcp::Util::readAll(int fd, void *buf, size_t count)
133  	{
134  	  size_t rc;
135  	  char *ptr = (char *) buf;
136  	  int num_read = 0;
At conditional (1): "num_read < count": Taking true branch.
137  	  for (num_read = 0; num_read < count;) {
Event neg_sink_parm_call: Passing "fd" to "read", which cannot accept a negative.
138  	    rc = read (fd, ptr + num_read, count - num_read);
139  	    if (rc == -1) {
140  	      if (errno == EINTR || errno == EAGAIN)
141  		continue;
142  	      else
143  	        return -1;
144  	    }
145  	    else if (rc == 0)
146  	      break;
147  	    else // else rc > 0
148  	      num_read += rc;
149  	  }
150  	  return num_read;
151  	}