/*
- * $Id: ad_open.c,v 1.56 2009-11-07 01:02:58 didg Exp $
+ * $Id: ad_open.c,v 1.60.2.1 2010-01-02 10:22:33 franklahm Exp $
*
* Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
* Copyright (c) 1990,1991 Regents of The University of Michigan.
{
static char modebuf[ MAXPATHLEN + 1];
char *slash;
- size_t len;
-
- if ( (len = strlen( path )) >= MAXPATHLEN ) {
- errno = ENAMETOOLONG;
- return NULL; /* can't do it */
- }
-
/*
* For a path with directories in it, remove the final component
* (path or subdirectory name) to get the name we want to stat.
* For a path which is just a filename, use "." instead.
*/
- strcpy( modebuf, path );
- slash = strrchr( modebuf, '/' );
- /* is last char a '/' */
- if (slash && slash[1] == 0) {
- while (modebuf < slash && slash[-1] == '/') {
- --slash;
+ slash = strrchr( path, '/' );
+ if (slash) {
+ size_t len;
+
+ len = slash - path;
+ if (len >= MAXPATHLEN) {
+ errno = ENAMETOOLONG;
+ return NULL; /* can't do it */
}
- if (modebuf < slash) {
+ memcpy( modebuf, path, len );
+ modebuf[len] = '\0';
+ /* is last char a '/' ? */
+ if (slash[1] == 0) {
+ slash = modebuf+ len;
+ /* remove them */
+ while (modebuf < slash && slash[-1] == '/') {
+ --slash;
+ }
+ if (modebuf == slash) {
+ goto use_cur;
+ }
+ *slash = '\0';
+ while (modebuf < slash && *slash != '/') {
+ --slash;
+ }
+ if (modebuf == slash) {
+ goto use_cur;
+ }
*slash = '\0'; /* remove pathname component */
- slash = strrchr( modebuf, '/' );
}
+ return modebuf;
}
- if (slash) {
- *slash = '\0'; /* remove pathname component */
- } else {
- modebuf[0] = '.'; /* use current directory */
- modebuf[1] = '\0';
- }
+use_cur:
+ modebuf[0] = '.'; /* use current directory */
+ modebuf[1] = '\0';
return modebuf;
}
if (!p) {
return -1;
}
-
- return stat( p, stbuf );
+//FIXME!
+ return lstat( p, stbuf );
}
/* ----------------
void ad_init(struct adouble *ad, int flags, int options)
{
- memset( ad, 0, sizeof( struct adouble ) );
+ ad->ad_inited = 0;
ad->ad_flags = flags;
if (flags == AD_VERSION2_OSX) {
ad->ad_ops = &ad_osx;
+ ad->ad_md = &ad->ad_resource_fork;
}
else if (flags == AD_VERSION1_SFM) {
ad->ad_ops = &ad_sfm;
+ ad->ad_md = &ad->ad_metadata_fork;
}
else {
ad->ad_ops = &ad_adouble;
+ ad->ad_md = &ad->ad_resource_fork;
}
ad->ad_options = options;
+
+ ad_data_fileno(ad) = -1;
+ ad_reso_fileno(ad) = -1;
+ ad_meta_fileno(ad) = -1;
+ /* following can be read even if there's no
+ * meda data.
+ */
+ memset(ad->ad_eid, 0, sizeof( ad->ad_eid ));
+ ad->ad_rlen = 0;
}
/* -------------------
{
struct stat st_dir;
struct stat st_meta;
+ struct stat st_link;
struct stat *pst = NULL;
char *ad_p;
int hoflags, admode;
int open_df = 0;
if (ad->ad_inited != AD_INITED) {
- ad_data_fileno(ad) = -1;
- ad_reso_fileno(ad) = -1;
- adf_lock_init(&ad->ad_data_fork);
- adf_lock_init(&ad->ad_resource_fork);
- if (ad->ad_flags != AD_VERSION1_SFM) {
- ad->ad_md = &ad->ad_resource_fork;
- }
- else {
- adf_lock_init(&ad->ad_metadata_fork);
- ad->ad_md = &ad->ad_metadata_fork;
- ad_meta_fileno(ad) = -1;
- }
ad->ad_inited = AD_INITED;
ad->ad_refcount = 1;
ad->ad_open_forks = 0;
ad->ad_adflags = adflags;
+ ad->ad_resource_fork.adf_refcount = 0;
+ ad->ad_data_fork.adf_refcount = 0;
+ ad->ad_data_fork.adf_syml=0;
}
else {
ad->ad_open_forks = ((ad->ad_data_fork.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
admode = mode;
}
}
- ad->ad_data_fork.adf_fd =open( path, hoflags, admode );
+ lstat(path,&st_link);
+ if (S_ISLNK(st_link.st_mode) && (oflags == O_RDONLY)) {
+ int lsz;
+ ad->ad_data_fork.adf_syml=(char *)malloc(PATH_MAX+1);
+ lsz=readlink(path,ad->ad_data_fork.adf_syml,PATH_MAX);
+ if (lsz<=0) {
+ free(ad->ad_data_fork.adf_syml);
+ return -1;
+ }
+ ad->ad_data_fork.adf_syml[lsz]=0;
+ ad->ad_data_fork.adf_syml=(char *)realloc(ad->ad_data_fork.adf_syml,lsz+1);
+ ad->ad_data_fork.adf_fd=0;
+ }else{
+
+ ad->ad_data_fork.adf_fd =open( path, hoflags | O_NOFOLLOW, admode );
+
if (ad->ad_data_fork.adf_fd < 0 ) {
if ((errno == EACCES || errno == EROFS) && !(oflags & O_RDWR)) {
hoflags = oflags;
- ad->ad_data_fork.adf_fd = open( path, hoflags, admode );
+ ad->ad_data_fork.adf_fd = open( path, hoflags | O_NOFOLLOW, admode );
+ }
}
}
if ( ad->ad_data_fork.adf_fd < 0)
/* just created, set owner if admin (root) */
ad_chown(path, &st_dir);
}
+ adf_lock_init(&ad->ad_data_fork);
}
else {
/* the file is already open... but */
goto sfm;
}
+ memset(ad->ad_eid, 0, sizeof( ad->ad_eid ));
+ ad->ad_rlen = 0;
ad_p = ad->ad_ops->ad_path( path, adflags );
hoflags = oflags & ~(O_CREAT | O_EXCL);
if (!(adflags & ADFLAGS_RDONLY)) {
hoflags = (hoflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
}
- ad->ad_md->adf_fd = open( ad_p, hoflags, 0 );
+ ad->ad_md->adf_fd = open( ad_p, hoflags | O_NOFOLLOW, 0 );
if (ad->ad_md->adf_fd < 0 ) {
if ((errno == EACCES || errno == EROFS) && !(oflags & O_RDWR)) {
hoflags = oflags & ~(O_CREAT | O_EXCL);
- ad->ad_md->adf_fd = open( ad_p, hoflags, 0 );
+ ad->ad_md->adf_fd = open( ad_p, hoflags | O_NOFOLLOW, 0 );
}
}
}
AD_SET(ad->ad_md->adf_off);
- memset(ad->ad_eid, 0, sizeof( ad->ad_eid ));
- ad->ad_md->adf_refcount++;
+ ad->ad_md->adf_refcount = 1;
+ adf_lock_init(ad->ad_md);
if ((ad->ad_md->adf_flags & ( O_TRUNC | O_CREAT ))) {
/*
* This is a new adouble header file. Initialize the structure,
ad_p = ad->ad_ops->ad_path( path, ADFLAGS_RF );
- hoflags = (oflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
- ad->ad_resource_fork.adf_fd = open( ad_p, hoflags, admode );
admode = mode;
st_invalid = ad_mode_st(ad_p, &admode, &st_dir);
admode = mode;
}
+ hoflags = (oflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
+ ad->ad_resource_fork.adf_fd = open( ad_p, hoflags, admode );
+
if (ad->ad_resource_fork.adf_fd < 0 ) {
if ((errno == EACCES || errno == EROFS) && !(oflags & O_RDWR)) {
hoflags = oflags;
errno = err;
return -1;
}
-
+ adf_lock_init(&ad->ad_resource_fork);
AD_SET(ad->ad_resource_fork.adf_off);
ad->ad_resource_fork.adf_flags = hoflags;
if ((oflags & O_CREAT) && !st_invalid) {
uid_t uid;
int ret, err;
int dir = flags & ADFLAGS_DIR;
-
+ int adouble = 0;
+
+ if (!(flags & ADFLAGS_NOADOUBLE)) {
+ adouble = O_CREAT;
+ }
+
/* Open with O_CREAT, thus enumarating a dir will create missing adouble files, see: */
/* http://marc.info/?l=netatalk-devel&m=124039156832408&w=2 */
- if ((ret = ad_open(name, ADFLAGS_HF | dir, O_RDWR | O_CREAT, 0666, adp)) < 0 && errno == EACCES) {
+ if ((ret = ad_open(name, ADFLAGS_HF | dir, O_RDWR | adouble, 0666, adp)) < 0 && errno == EACCES) {
uid = geteuid();
if (seteuid(0)) {
LOG(log_error, logtype_default, "ad_metadata(%s): seteuid failed %s", name, strerror(errno));
memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
}
- if (stat(path, &st) < 0) {
+ if (lstat(path, &st) < 0) {
return -1;
}