Statistics
| Branch: | Tag: | Revision:

dvbd / utils.cpp @ bfdb7446

History | View | Annotate | Download (3.29 KB)

1
/*
2
  Copyright 2003 John Knottenbelt
3
  
4
  This program is free software; you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation; either version 2 of the License, or
7
  (at your option) any later version.
8
 
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
 
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17
*/
18

    
19
#include "config.h"
20
#include "utils.h"
21
#include <fcntl.h>
22
#include <sys/types.h>
23
#include <sys/socket.h>
24
#include <sys/stat.h>
25
#include <unistd.h>
26
#include <iostream>
27
#include <cctype>
28

    
29
void setNonBlocking(int fd)
30
{
31
  long flags = fcntl(fd, F_GETFL, 0); 
32
  flags |= O_NONBLOCK;
33
  fcntl(fd, F_SETFL, flags);
34
}
35

    
36
int readLineStripTrailingWS(int fd, std::string &line)
37
{
38
  char data[1024];
39
  int bytesread = read(fd, data, 1023);
40

    
41
  if (bytesread <= 0)
42
    return bytesread;
43

    
44
  data[bytesread] = '\x0';
45

    
46
  // Strip trailing whitespace;
47
  for (int j = bytesread - 1; j >= 0 && isspace(data[j]); j--)
48
    data[j] = '\x0';
49

    
50
  line = data;
51
  return bytesread;
52
}
53

    
54
void writeString(int fd, const std::string &line)
55
{
56
  write(fd, line.data(), line.size());
57
}
58

    
59
std::string escapeWS(const std::string &channel)
60
{
61
  std::string result;
62

    
63
  for (unsigned i = 0; i < channel.size(); i++) {
64
    switch (channel[i]) {
65
    case '\\':
66
      result += "\\\\";
67
      break;
68
    case ' ':
69
      result += "\\_";
70
      break;
71
    default:
72
      result += channel[i];
73
    }
74
  }
75

    
76
  return result;
77
}
78

    
79
std::string unescapeWS(const std::string &channel)
80
{
81
  std::string result;
82
  bool escaped = false;
83

    
84
  for (unsigned i = 0; i < channel.size(); i++) {
85
    if (channel[i] == '\\')
86
      escaped = true;
87
    else {
88
      char ch = channel[i];
89

    
90
      if (escaped && ch == '_') {
91
        ch = ' ';
92
        escaped = false;
93
      }
94

    
95
      result += ch;
96
    }
97
  }
98
  return result;
99
}
100

    
101
bool readCredentials(int fd, pid_t &pid, uid_t &uid, gid_t &gid)
102
{
103
  int value = 1;
104
  if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &value, sizeof(value)) < 0) 
105
    std::cerr << "Failed to set SOL_SOCKET SO_PASSCRED: " << strerror(errno) << "\n";
106

    
107
  struct ucred ucred;
108
  socklen_t size = sizeof(ucred);
109
  if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &size) < 0) {
110
    std::cerr << "Failed to get credentials from UNIX socket: " 
111
              << strerror(errno) << "\n";
112
    return false;  
113
  }
114

    
115
  pid = ucred.pid;
116
  uid = ucred.uid;
117
  gid = ucred.gid;
118
  return true;
119
}
120

    
121
bool accessOk(const std::string &path, uid_t uid)
122
{
123
  std::string::size_type lastSlash = path.find_last_of('/');
124
  if (lastSlash == std::string::npos) 
125
    return false;
126

    
127
  std::string dirPart = path.substr(0, lastSlash);
128
  std::string filePart = path.substr(lastSlash + 1);
129

    
130
  // Client must own directory
131
  struct stat info;
132
  if (stat(dirPart.c_str(), &info) != 0)
133
    return false;
134
  
135
  if (info.st_uid != uid)
136
    return false;
137

    
138
  // But must still be writable by this process
139
  if (access(path.c_str(), F_OK) == 0)
140
    return access(path.c_str(), W_OK) == 0;
141
  else 
142
    return access(dirPart.c_str(), W_OK) == 0;
143
}
144