XRootD
Loading...
Searching...
No Matches
XrdOssMSS.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d O s s M S S . c c */
4/* */
5/* (C) 2003 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* All Rights Reserved */
7/* Produced by Andrew Hanushevsky for Stanford University under contract */
8/* DE-AC02-76-SFO0515 with the Deprtment of Energy */
9/* */
10/* This file is part of the XRootD software suite. */
11/* */
12/* XRootD is free software: you can redistribute it and/or modify it under */
13/* the terms of the GNU Lesser General Public License as published by the */
14/* Free Software Foundation, either version 3 of the License, or (at your */
15/* option) any later version. */
16/* */
17/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20/* License for more details. */
21/* */
22/* You should have received a copy of the GNU Lesser General Public License */
23/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25/* */
26/* The copyright holder's institutional names and contributor's names may not */
27/* be used to endorse or promote products derived from this software without */
28/* specific prior written permission of the institution or contributor. */
29/******************************************************************************/
30
31#include <dirent.h>
32#include <unistd.h>
33#include <cerrno>
34#include <strings.h>
35#include <signal.h>
36#include <cstdio>
37#include <ctime>
38#if defined(AIX) || defined(__solaris__)
39#include <sys/vnode.h>
40#include <sys/mode.h>
41#endif
42#include <sys/param.h>
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <sys/wait.h>
46
47#include "XrdNet/XrdNetOpts.hh"
49#include "XrdOss/XrdOssApi.hh"
51#include "XrdOss/XrdOssError.hh"
52#include "XrdOss/XrdOssTrace.hh"
53#include "XrdOuc/XrdOucProg.hh"
55#include "XrdSys/XrdSysError.hh"
59
60/******************************************************************************/
61/* E r r o r R o u t i n g O b j e c t */
62/******************************************************************************/
63
65
67
68/******************************************************************************/
69/* d e f i n e s */
70/******************************************************************************/
71
72#define NegVal(x) (x <= 0 ? (x < 0 ? x : -1) : -x)
73
74/******************************************************************************/
75/* f i l e h a n d l e */
76/******************************************************************************/
77
78/* These are private data structures. They are allocated dynamically to the
79 appropriate size (yes, that means dbx has a tough time).
80*/
81
83 {int hflag;
85
86 XrdOssHandle(int type, XrdOucStream *newsp=0) {hflag = type; sp = newsp;}
87 ~XrdOssHandle() {if (sp) delete sp; hflag = 0;}
88
89 };
90
91#define XRDOSS_HT_EOF 1
92#define XRDOSS_HT_DIR 4
93
94/******************************************************************************/
95/* M a s s S t o r a g e R e l a t e d M e t h o d s */
96/******************************************************************************/
97
98/******************************************************************************/
99/* o p e n d i r */
100/******************************************************************************/
101
102void *XrdOssSys::MSS_Opendir(const char *dir_path, int &rc) {
103/*
104 Function: Open the directory `path' and prepare for reading.
105
106 Input: path - The fully qualified name of the directory to open.
107
108 Output: Returns a directory handle to be used for subsequent
109 operations. If an error occurs, (-errno) is returned.
110*/
111 const char *epname = "MSS_Opendir";
112 struct XrdOssHandle *oh;
113 XrdOucStream *sp;
114
115 // Make sure the path is not too long.
116 //
117 if (strlen(dir_path) > MAXPATHLEN)
118 {OssEroute.Emsg(epname, "mss path too long - ", dir_path);
119 rc = -ENAMETOOLONG;
120 return (void *)0;
121 }
122
123 // Issue it now to trap any errors but defer reading the result until
124 // readdir() is called. This does tie up a process, sigh.
125 //
126 if ( (rc = MSS_Xeq(&sp, ENOENT, "dlist", dir_path)))
127 return (void *)0;
128
129 // Allocate storage for the handle and return a copy of it.
130 //
131 if (!(oh = new XrdOssHandle(XRDOSS_HT_DIR, sp)))
132 {delete sp; rc = -ENOMEM; return (void *)0;}
133 return (void *)oh;
134}
135
136/******************************************************************************/
137/* r e a d d i r */
138/******************************************************************************/
139
140int XrdOssSys::MSS_Readdir(void *dir_handle, char *buff, int blen) {
141/*
142 Function: Read the next entry if directory 'dir_handle'.
143
144 Input: dir_handle - The value returned by a successful opendir() call.
145 buff - Buffer to hold directory name.
146 blen - Size of the buffer.
147
148 Output: Upon success, places the contents of the next directory entry
149 in buff. When the end of the directory is encountered buff
150 will be set to a null string.
151
152 Upon failure, returns a (-errno).
153*/
154 const char *epname = "MSS_Readdir";
155 int retc;
156 struct XrdOssHandle *oh = (struct XrdOssHandle *)dir_handle;
157 char *resp;
158
159 // Verify that the handle is correct.
160 //
161 if ( !(oh->hflag & XRDOSS_HT_DIR) )
162 {OssEroute.Emsg(epname, "invalid mss handle"); return -EBADF;}
163
164 // Read a record from the directory, if possible.
165 //
166 if (oh->hflag & XRDOSS_HT_EOF) *buff = '\0';
167 else if ((resp = oh->sp->GetLine()))
168 {if ( ((int)strlen(resp)) >= blen )
169 {*buff = '\0';
170 return OssEroute.Emsg(epname, -EOVERFLOW,
171 "readdir rmt", resp);
172 }
173 strlcpy(buff, resp, blen);
174 } else {
175 if ((retc = oh->sp->LastError())) return NegVal(retc);
176 else {*buff = '\0'; oh->hflag |= XRDOSS_HT_EOF;}
177 }
178 return XrdOssOK;
179}
180
181/******************************************************************************/
182/* c l o s e d i r */
183/******************************************************************************/
184
185int XrdOssSys::MSS_Closedir(void *dir_handle) {
186/*
187 Function: Close the directory associated with handle "dir_handle".
188
189 Input: dir_handle - The handle returned by opendir().
190
191 Output: Returns 0 upon success and (-errno) upon failure.
192*/
193 const char *epname = "MSS_Closedir";
194 struct XrdOssHandle *oh = (struct XrdOssHandle *)dir_handle;
195
196 if ( !(oh->hflag & XRDOSS_HT_DIR) )
197 {OssEroute.Emsg(epname, "invalid mss handle"); return -EBADF;}
198 delete oh;
199 return XrdOssOK;
200}
201
202/******************************************************************************/
203/* c r e a t e */
204/******************************************************************************/
205
206int XrdOssSys::MSS_Create(const char *path, mode_t file_mode, XrdOucEnv &env)
207/*
208 Function: Create a file named `path' with 'file_mode' access mode bits set.
209
210 Input: path - The fully qualified name of the file to create.
211 file_mode - The Posix access mode bits to be assigned to the file.
212 These bits correspond to the standard Unix permission
213 bits (e.g., 744 == "rwxr--r--").
214 env Enviornmental information.
215
216 Output: Returns zero upon success and (-errno) otherwise.
217*/
218{
219 const char *epname = "MSS_Create";
220 char myMode[16];
221
222 // Make sure the path is not too long.
223 //
224 if (strlen(path) > MAXPATHLEN)
225 {OssEroute.Emsg(epname, "mss path too long - ", path);
226 return -ENAMETOOLONG;
227 }
228
229 // Construct the cmd to create the file. We currently don't support cosid.
230 //
231 sprintf(myMode, "%o", static_cast<int>(file_mode));
232
233 // Create the file in in the mass store system
234 //
235 return MSS_Xeq(0, 0, "create", path, myMode);
236}
237
238
239/******************************************************************************/
240/* s t a t */
241/******************************************************************************/
242
243/*
244 Function: Determine if file 'path' actually exists.
245
246 Input: path - Is the fully qualified name of the file to be tested.
247 buff - pointer to a 'stat' structure to hold the attributes
248 of the file.
249
250 Output: Returns 0 upon success and -errno upon failure.
251*/
252
253int XrdOssSys::MSS_Stat(const char *path, struct stat *buff)
254{
255 const char *epname = "MSS_Stat";
256 char ftype, mtype[10], *resp;
257 int retc, xt_nlink;
258 long xt_uid, xt_gid, atime, ctime, mtime, xt_blksize, xt_blocks;
259 long long xt_size;
260 XrdOucStream *sfd;
261
262 // Make sure the path is not too long.
263 //
264 if (strlen(path) > MAXPATHLEN)
265 {OssEroute.Emsg(epname, "mss path too long - ", path);
266 return -ENAMETOOLONG;
267 }
268
269 // Issue the command. This may be an immediate exists a or full statx.
270 //
271 if (!buff) return MSS_Xeq(0, ENOENT, (isMSSC ? "statx" : "exists"), path);
272 if ((retc = MSS_Xeq(&sfd, ENOENT, "statx", path))) return retc;
273
274 // Read in the results.
275 //
276 if ( !(resp = sfd ->GetLine()))
277 return OssEroute.Emsg(epname,-XRDOSS_E8012,"process ",path);
278
279 // Extract data from the response.
280 //
281 sscanf(resp, "%c %9s %d %ld %ld %ld %ld %ld %lld %ld %ld", &ftype, mtype,
282 &xt_nlink, &xt_uid, &xt_gid, &atime, &ctime, &mtime,
283 &xt_size, &xt_blksize, &xt_blocks);
284
285 // Set the stat buffer, appropriately.
286 //
287 memset( (char *)buff, 0, sizeof(struct stat) );
288 buff->st_nlink = static_cast<nlink_t>(xt_nlink);
289 buff->st_uid = static_cast<uid_t>(xt_uid);
290 buff->st_gid = static_cast<gid_t>(xt_gid);
291 buff->st_atime = static_cast<time_t>(atime);
292 buff->st_ctime = static_cast<time_t>(ctime);
293 buff->st_mtime = static_cast<time_t>(mtime);
294 buff->st_size = static_cast<off_t>(xt_size);
295 buff->st_blksize=static_cast<long>(xt_blksize);
296#ifdef __APPLE__
297 buff->st_blocks = xt_blocks;
298#else
299 buff->st_blocks =static_cast<blkcnt_t>(xt_blocks);
300#endif
301
302 if (ftype == 'd') buff->st_mode |= S_IFDIR;
303 else if (ftype == 'l') buff->st_mode |= S_IFLNK;
304 else buff->st_mode |= S_IFREG;
305
306 buff->st_mode |= tranmode(&mtype[0]) << 6;
307 buff->st_mode |= tranmode(&mtype[3]) << 3;
308 buff->st_mode |= tranmode(&mtype[6]);
309
310 delete sfd;
311 return 0;
312}
313
314int XrdOssSys::tranmode(char *mode) {
315 int mbits = 0;
316 if (mode[0] == 'r') mbits |= S_IROTH;
317 if (mode[1] == 'w') mbits |= S_IWOTH;
318 if (mode[2] == 'x') mbits |= S_IXOTH;
319 return mbits;
320}
321
322/******************************************************************************/
323/* r e m o v e */
324/******************************************************************************/
325
326/*
327 Function: Delete a file from the namespace and release it's data storage.
328
329 Input: path - Is the fully qualified name of the file to be removed.
330
331 Output: Returns 0 upon success and -errno upon failure.
332*/
333int XrdOssSys::MSS_Unlink(const char *path) {
334 const char *epname = "MSS_Unlink";
335
336 // Make sure the path is not too long.
337 //
338 if (strlen(path) > MAXPATHLEN)
339 {OssEroute.Emsg(epname, "mss path too long - ", path);
340 return -ENAMETOOLONG;
341 }
342
343 // Remove the file in Mass Store System.
344 //
345 return MSS_Xeq(0, ENOENT, "rm", path);
346}
347
348/******************************************************************************/
349/* r e n a m e */
350/******************************************************************************/
351
352/*
353 Function: Renames a file with name 'old_name' to 'new_name'.
354
355 Input: old_name - Is the fully qualified name of the file to be renamed.
356 new_name - Is the fully qualified name that the file is to have.
357
358 Output: Returns 0 upon success and -errno upon failure.
359*/
360int XrdOssSys::MSS_Rename(const char *oldname, const char *newname) {
361 const char *epname = "MSS_Rename";
362
363 // Make sure the path is not too long.
364 //
365 if (strlen(oldname) > MAXPATHLEN
366 || strlen(newname) > MAXPATHLEN)
367 {OssEroute.Emsg(epname,"mss path too long - ", oldname, newname);
368 return -ENAMETOOLONG;
369 }
370
371 // Rename the file in Mass Store System
372 //
373 return MSS_Xeq(0, 0, "mv", oldname, newname);
374}
375
376/******************************************************************************/
377/* P R I V A T E S E C T I O N */
378/******************************************************************************/
379/******************************************************************************/
380/* M S S _ X e q */
381/******************************************************************************/
382
383int XrdOssSys::MSS_Xeq(XrdOucStream **xfd, int okerr,
384 const char *cmd, const char *arg1, const char *arg2)
385{
386 EPNAME("MSS_Xeq")
387 static int NoResp = 0;
388 char *resp;
389 int retc;
390 XrdOucStream *sp;
391
392// If we have no gateway command, return an error
393//
394 if (!RSSProg) return -XRDOSS_E8013;
395
396// Allocate a stream for this command
397//
398 if (!(sp = new XrdOucStream(&OssEroute)))
399 return OssEroute.Emsg("MSS_Xeq",-ENOMEM,"create stream for",RSSCmd);
400
401// Run the command
402//
403 DEBUG("Invoking '" <<RSSCmd <<' ' <<cmd <<' ' <<(arg1 ? arg1 : "")
404 <<' ' <<(arg2 ? arg2 : ""));
405 if ((retc = RSSProg->Run(sp, cmd, arg1, arg2)))
406 {delete sp; return NegVal(retc);}
407
408// Wait for data to appear. We do this to avoid hanging up and chewing through
409// all of the threads while clients retry the requests with a new connection.
410//
411 if ((retc = sp->Wait4Data(RSSTout)))
412 {if (retc < 0)
413 {if (!(0xff & NoResp++))
414 OssEroute.Emsg("MSS_Xeq", -ETIMEDOUT, "execute", cmd);
415 retc = ETIMEDOUT;
416 }
417 delete sp; return NegVal(retc);
418 }
419
420// Read back the first record. The first records must be the return code
421// from the command followed by any output. Make sure that this is the case.
422//
423 if ( !(resp = sp->GetLine()) ) retc = XRDOSS_E8023;
424 else
425 {DEBUG("received '" <<resp <<"'");
426 if (sscanf(resp, "%d", &retc) <= 0) retc = XRDOSS_E8024;
427 }
428 if (retc)
429 {if (retc != -okerr)
430 OssEroute.Emsg("MSS_Xeq", NegVal(retc), "execute", cmd);
431 delete sp;
432 return NegVal(retc);
433 }
434
435// If the caller wants the stream pointer; return it. Otherwise close it.
436//
437 if (xfd) *xfd = sp;
438 else delete sp;
439 return 0;
440}
#define DEBUG(x)
#define EPNAME(x)
XrdSysTrace OssTrace
XrdSysError OssEroute
#define XRDOSS_E8013
#define XRDOSS_E8023
#define XRDOSS_E8012
#define XRDOSS_E8024
#define XRDOSS_HT_DIR
Definition XrdOssMSS.cc:92
#define NegVal(x)
Definition XrdOssMSS.cc:72
#define XRDOSS_HT_EOF
Definition XrdOssMSS.cc:91
#define XrdOssOK
Definition XrdOss.hh:50
#define stat(a, b)
Definition XrdPosix.hh:96
size_t strlcpy(char *dst, const char *src, size_t sz)
int MSS_Readdir(void *fd, char *buff, int blen)
Definition XrdOssMSS.cc:140
int MSS_Rename(const char *, const char *)
Definition XrdOssMSS.cc:360
int tranmode(char *)
Definition XrdOssMSS.cc:314
int MSS_Closedir(void *)
Definition XrdOssMSS.cc:185
int MSS_Unlink(const char *)
Definition XrdOssMSS.cc:333
XrdOucProg * RSSProg
Definition XrdOssApi.hh:307
int MSS_Stat(const char *, struct stat *buff=0)
Definition XrdOssMSS.cc:253
int MSS_Create(const char *path, mode_t, XrdOucEnv &)
Definition XrdOssMSS.cc:206
int MSS_Xeq(XrdOucStream **xfd, int okerr, const char *cmd, const char *arg1=0, const char *arg2=0)
Definition XrdOssMSS.cc:383
char * RSSCmd
Definition XrdOssApi.hh:238
void * MSS_Opendir(const char *, int &rc)
Definition XrdOssMSS.cc:102
char * GetLine()
int Wait4Data(int msMax=-1)
XrdOssHandle(int type, XrdOucStream *newsp=0)
Definition XrdOssMSS.cc:86
XrdOucStream * sp
Definition XrdOssMSS.cc:84