00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdOssCreateCVSID = "$Id: XrdOssCreate.cc 34000 2010-06-21 06:49:56Z ganis $";
00014
00015
00016
00017
00018
00019 #include <unistd.h>
00020 #include <errno.h>
00021 #include <fcntl.h>
00022 #include <strings.h>
00023 #include <stdio.h>
00024 #include <sys/file.h>
00025 #include <sys/stat.h>
00026 #include <sys/types.h>
00027 #include <sys/param.h>
00028 #if defined(__solaris__) || defined(AIX)
00029 #include <sys/vnode.h>
00030 #endif
00031
00032 #include "XrdOss/XrdOssApi.hh"
00033 #include "XrdOss/XrdOssCache.hh"
00034 #include "XrdOss/XrdOssConfig.hh"
00035 #include "XrdOss/XrdOssCopy.hh"
00036 #include "XrdOss/XrdOssError.hh"
00037 #include "XrdOss/XrdOssLock.hh"
00038 #include "XrdOss/XrdOssOpaque.hh"
00039 #include "XrdOss/XrdOssPath.hh"
00040 #include "XrdOss/XrdOssSpace.hh"
00041 #include "XrdOss/XrdOssTrace.hh"
00042 #include "XrdOuc/XrdOuca2x.hh"
00043 #include "XrdOuc/XrdOucEnv.hh"
00044 #include "XrdOuc/XrdOucExport.hh"
00045 #include "XrdOuc/XrdOucUtils.hh"
00046 #include "XrdSys/XrdSysError.hh"
00047 #include "XrdSys/XrdSysHeaders.hh"
00048 #include "XrdSys/XrdSysPlatform.hh"
00049
00050
00051
00052
00053
00054 extern XrdSysError OssEroute;
00055
00056 extern XrdOucTrace OssTrace;
00057
00058 extern XrdOssSys *XrdOssSS;
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 int XrdOssSys::Create(const char *tident, const char *path, mode_t access_mode,
00080 XrdOucEnv &env, int Opts)
00081 {
00082 EPNAME("Create")
00083 const int LKFlags = XrdOssFILE|XrdOssSHR|XrdOssNOWAIT|XrdOssRETIME;
00084 const int AMode = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH;
00085 char local_path[MAXPATHLEN+1], *p, pc;
00086 unsigned long long popts, remotefs;
00087 int isLink = 0, Missing = 1, retc = 0, datfd;
00088 XrdOssLock path_dir, new_file;
00089 struct stat buf;
00090
00091
00092
00093 remotefs = Check_RO(Create, popts, path, "create");
00094
00095
00096
00097 if ((retc = GenLocalPath(path, local_path))) return retc;
00098
00099
00100
00101 if ((Missing = lstat(local_path, &buf))) retc = errno;
00102 else {if ((isLink = ((buf.st_mode & S_IFMT) == S_IFLNK)))
00103 {if (stat(local_path, &buf))
00104 {if (errno != ENOENT) return -errno;
00105 OssEroute.Emsg("Create","removing dangling link",local_path);
00106 if (unlink(local_path)) retc = errno;
00107 Missing = 1; isLink = 0;
00108 }
00109 }
00110 }
00111 if (retc && retc != ENOENT) return -retc;
00112
00113
00114
00115
00116 if (StageCreate && Missing)
00117 return XrdOssSS->Stage(tident, path, env, Opts>>8, access_mode, popts);
00118
00119
00120
00121 if (!Missing)
00122 {if (Opts & XRDOSS_new) return -EEXIST;
00123 if ((buf.st_mode & S_IFMT) == S_IFDIR) return -EISDIR;
00124 do {datfd = open(local_path, Opts>>8, access_mode);}
00125 while(datfd < 0 && errno == EINTR);
00126 if (datfd < 0) return -errno;
00127 close(datfd);
00128 if (Opts>>8 & O_TRUNC && buf.st_size)
00129 {off_t theSize = buf.st_size;
00130 if (isLink) {buf.st_mode = (buf.st_mode & ~S_IFMT) | S_IFLNK;
00131 XrdOssCache::Adjust(local_path, -theSize, &buf);
00132 }
00133 }
00134 return 0;
00135 }
00136
00137
00138
00139 if ((Opts & XRDOSS_mkpath) && (p = rindex(local_path, '/')))
00140 {p++; pc = *p; *p = '\0';
00141 XrdOucUtils::makePath(local_path, AMode);
00142 *p = pc;
00143 }
00144
00145
00146
00147 if (remotefs)
00148 {char remote_path[MAXPATHLEN+1];
00149
00150
00151
00152 if ((retc = GenRemotePath(path,remote_path))) return retc;
00153
00154
00155
00156 if ( (retc = path_dir.Serialize(local_path, XrdOssDIR|XrdOssEXC)) < 0)
00157 return retc;
00158
00159
00160
00161 if (popts & XRDEXP_RCREATE)
00162 {if ((retc = MSS_Create(remote_path, access_mode, env)) < 0)
00163 {path_dir.UnSerialize(0);
00164 DEBUG("rc" <<retc <<" mode=" <<std::oct <<access_mode
00165 <<std::dec <<" remote path=" <<remote_path);
00166 return retc;
00167 }
00168 } else if (!(popts & XRDEXP_NOCHECK))
00169 {if (!(retc = MSS_Stat(remote_path)))
00170 {path_dir.UnSerialize(0); return -EEXIST;}
00171 else if (retc != -ENOENT)
00172 {path_dir.UnSerialize(0); return retc;}
00173 }
00174 }
00175
00176
00177
00178 if (XrdOssCache::fsfirst && !(popts & XRDEXP_INPLACE))
00179 retc = Alloc_Cache(local_path, access_mode, env);
00180 else retc = Alloc_Local(local_path, access_mode, env);
00181
00182
00183
00184 if (retc == XrdOssOK && (popts & XRDEXP_MAKELF))
00185 if (new_file.Serialize(local_path,LKFlags) >= 0) new_file.UnSerialize(0);
00186
00187
00188
00189 if (remotefs) path_dir.UnSerialize(0);
00190 return retc;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200 int XrdOssSys::Alloc_Cache(const char *path, mode_t amode, XrdOucEnv &env)
00201 {
00202 EPNAME("Alloc_Cache")
00203 int datfd;
00204 char pbuff[MAXPATHLEN+1], cgbuff[XrdOssSpace::minSNbsz], *tmp;
00205 XrdOssCache::allocInfo aInfo(path, pbuff, sizeof(pbuff));
00206
00207
00208
00209 if ((tmp = env.Get(OSS_ASIZE))
00210 && !XrdOuca2x::a2ll(OssEroute,"invalid asize",tmp,&aInfo.cgSize,0))
00211 return -XRDOSS_E8018;
00212
00213
00214
00215 if ((aInfo.cgPath=XrdOssCache::Parse(env.Get(OSS_CGROUP),cgbuff,sizeof(cgbuff))))
00216 aInfo.cgPlen = strlen(aInfo.cgPath);
00217
00218
00219
00220 aInfo.cgName = cgbuff;
00221 aInfo.aMode = amode;
00222 if ((datfd = XrdOssCache::Alloc(aInfo)) < 0) return datfd;
00223 close(datfd);
00224
00225
00226
00227 if ((symlink(pbuff, path) && errno != EEXIST)
00228 || unlink(path) || symlink(pbuff, path)) {datfd = -errno; unlink(pbuff);}
00229
00230
00231
00232 if (aInfo.cgPsfx)
00233 {strcpy(aInfo.cgPsfx, ".pfn");
00234 if ((symlink(path, pbuff) && errno != EEXIST)
00235 || unlink(pbuff) || symlink(path, pbuff)) datfd = -errno;
00236 *(aInfo.cgPsfx) = '\0';
00237 if (datfd < 0) {unlink(pbuff); unlink(path);}
00238 }
00239
00240
00241
00242 DEBUG(aInfo.cgName <<" cache for " <<pbuff);
00243 return (datfd >= 0 ? XrdOssOK : datfd);
00244 }
00245
00246
00247
00248
00249
00250 int XrdOssSys::Alloc_Local(const char *path, mode_t amode, XrdOucEnv &env)
00251 {
00252 int datfd;
00253
00254
00255
00256 do {datfd = open(path, O_CREAT|O_TRUNC, amode);}
00257 while(datfd < 0 && errno == EINTR);
00258 if (datfd < 0) return -errno;
00259 close(datfd);
00260 return XrdOssOK;
00261 }