Exemple #1
0
/* use refcounts so that we don't have to re-establish fcntl locks. */
int ad_close( struct adouble *ad, int adflags)
{
    int         err = 0;

    if ((adflags & ADFLAGS_DF)
        && (ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == -2) /* -2 means symlink */
        && --ad->ad_data_fork.adf_refcount == 0) {
        if (ad->ad_data_fork.adf_syml != NULL) {
            free(ad->ad_data_fork.adf_syml);
            ad->ad_data_fork.adf_syml = 0;
        } else {
            if ( close( ad_data_fileno(ad) ) < 0 )
                err = -1;
        }
        ad_data_fileno(ad) = -1;
        adf_lock_free(&ad->ad_data_fork);
    }

    if (!( adflags & ADFLAGS_HF )) {
        return err;
    }

    /* meta /resource fork */

    if ( ad_meta_fileno(ad) != -1 && !(--ad->ad_md->adf_refcount)) {
        if ( close( ad_meta_fileno(ad) ) < 0 ) {
            err = -1;
        }
        ad_meta_fileno(ad) = -1;
        adf_lock_free(ad->ad_md);
    }

    if (ad->ad_flags != AD_VERSION1_SFM) {
        return err;
    }

    if ((adflags & ADFLAGS_DIR)) {
        return err;
    }

    if ( ad_reso_fileno(ad) != -1 && !(--ad->ad_resource_fork.adf_refcount)) {
        if ( close( ad_reso_fileno(ad) ) < 0 ) {
            err = -1;
        }
        ad_reso_fileno(ad) = -1;
        adf_lock_free(&ad->ad_resource_fork);
    }

    return err;
}
Exemple #2
0
/* --------------------- */
void ad_unlock(struct adouble *ad, const int fork, int unlckbrl)
{
    LOG(log_debug, logtype_default, "ad_unlock(unlckbrl: %d): BEGIN", unlckbrl);

    if (ad_data_fileno(ad) != -1) {
        adf_unlock(ad, &ad->ad_data_fork, fork, unlckbrl);
    }
    if (ad_reso_fileno(ad) != -1) {
        adf_unlock(ad, &ad->ad_resource_fork, fork, unlckbrl);
    }

    LOG(log_debug, logtype_default, "ad_unlock: END");
}
Exemple #3
0
static int getforkparams(struct ofork *ofork, u_int16_t bitmap, char *buf, size_t *buflen)
{
    struct path         path;
    struct stat		*st;

    struct adouble	*adp;
    struct dir		*dir;
    struct vol		*vol;
    

    /* can only get the length of the opened fork */
    if ( ( (bitmap & ((1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN))) 
                  && (ofork->of_flags & AFPFORK_RSRC)) 
        ||
          ( (bitmap & ((1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN))) 
                  && (ofork->of_flags & AFPFORK_DATA))) {
        return( AFPERR_BITMAP );
    }

    if ( ad_reso_fileno( ofork->of_ad ) == -1 ) { /* META ? */
        adp = NULL;
    } else {
        adp = ofork->of_ad;
    }

    vol = ofork->of_vol;
    dir = dirlookup(vol, ofork->of_did);

    if (NULL == (path.u_name = mtoupath(vol, of_name(ofork), dir->d_did, utf8_encoding()))) {
        return( AFPERR_MISC );
    }
    path.m_name = of_name(ofork);
    path.id = 0;
    st = &path.st;
    if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) | 
                    (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) | 
                    (1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) {
        if ( ad_data_fileno( ofork->of_ad ) <= 0 ) {
            /* 0 is for symlink */
            if (movecwd(vol, dir) < 0)
                return( AFPERR_NOOBJ );
            if ( lstat( path.u_name, st ) < 0 )
                return( AFPERR_NOOBJ );
        } else {
            if ( fstat( ad_data_fileno( ofork->of_ad ), st ) < 0 ) {
                return( AFPERR_BITMAP );
            }
        }
    }
    return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp );
}
Exemple #4
0
/* ------------------------------- */
int ad_readfile_init(const struct adouble *ad, 
				       const int eid, off_t *off,
				       const int end)
{
  int fd;

  if (end) 
    *off = ad_size(ad, eid) - *off;

  if (eid == ADEID_DFORK) {
    fd = ad_data_fileno(ad);
  } else {
    *off += ad_getentryoff(ad, eid);
    fd = ad_reso_fileno(ad);
  }

  return fd;
}
Exemple #5
0
static int fork_setmode(const AFPObj *obj, struct adouble *adp, int eid, int access, int ofrefnum)
{
    int ret;
    int readset;
    int writeset;
    int denyreadset;
    int denywriteset;

    if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
        return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_NONE, 1, ofrefnum);
    }

    if ((access & (OPENACC_RD | OPENACC_DRD))) {
        if ((readset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
            return readset;
        if ((denyreadset = ad_testlock(adp, eid, AD_FILELOCK_DENY_RD)) <0)
            return denyreadset;

        if ((access & OPENACC_RD) && denyreadset) {
            errno = EACCES;
            return -1;
        }
        if ((access & OPENACC_DRD) && readset) {
            errno = EACCES;
            return -1;
        }
        /* boolean logic is not enough, because getforkmode is not always telling the
         * true
         */
        if ((access & OPENACC_RD)) {
            ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_RD, 1, ofrefnum);
            if (ret)
                return ret;
        }
        if ((access & OPENACC_DRD)) {
            ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_RD, 1, ofrefnum);
            if (ret)
                return ret;
        }
    }
    /* ------------same for writing -------------- */
    if ((access & (OPENACC_WR | OPENACC_DWR))) {
        if ((writeset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
            return writeset;
        if ((denywriteset = ad_testlock(adp, eid, AD_FILELOCK_DENY_WR)) <0)
            return denywriteset;

        if ((access & OPENACC_WR) && denywriteset) {
            errno = EACCES;
            return -1;
        }
        if ((access & OPENACC_DWR) && writeset) {
            errno = EACCES;
            return -1;
        }
        if ((access & OPENACC_WR)) {
            ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_WR, 1, ofrefnum);
            if (ret)
                return ret;
        }
        if ((access & OPENACC_DWR)) {
            ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_WR, 1, ofrefnum);
            if (ret)
                return ret;
        }
    }

    /*
     * Fix for Bug 560: put the Solaris share reservation after our locking stuff.
     * Note that this still leaves room for a race condition where between placing our own
     * locks above and putting the Solaris share move below another client puts a lock.
     * We then end up with set locks from above and return with an error code, the proper
     * fix requires a sane cleanup function for the error path in this function.
     */

#ifdef HAVE_FSHARE_T
    fshare_t shmd;

    if (obj->options.flags & OPTION_SHARE_RESERV) {
        shmd.f_access = (access & OPENACC_RD ? F_RDACC : 0) | (access & OPENACC_WR ? F_WRACC : 0);
        if (shmd.f_access == 0)
            /* we must give an access mode, otherwise fcntl will complain */
            shmd.f_access = F_RDACC;
        shmd.f_deny = (access & OPENACC_DRD ? F_RDDNY : F_NODNY) | (access & OPENACC_DWR) ? F_WRDNY : 0;
        shmd.f_id = ofrefnum;

        int fd = (eid == ADEID_DFORK) ? ad_data_fileno(adp) : ad_reso_fileno(adp);

        if (fd != -1 && fd != AD_SYMLINK && fcntl(fd, F_SHARE, &shmd) != 0) {
            LOG(log_debug, logtype_afpd, "fork_setmode: fcntl: %s", strerror(errno));
            errno = EACCES;
            return -1;
        }
    }
#endif

    return 0;
}
Exemple #6
0
static int fork_setmode(const AFPObj *obj, struct adouble *adp, int eid, int access, int ofrefnum)
{
    int ret;
    int readset;
    int writeset;
    int denyreadset;
    int denywriteset;

#ifdef HAVE_FSHARE_T
    fshare_t shmd;

    if (obj->options.flags & OPTION_SHARE_RESERV) {
        shmd.f_access = (access & OPENACC_RD ? F_RDACC : 0) | (access & OPENACC_WR ? F_WRACC : 0);
        if (shmd.f_access == 0)
            /* we must give an access mode, otherwise fcntl will complain */
            shmd.f_access = F_RDACC;
        shmd.f_deny = (access & OPENACC_DRD ? F_RDDNY : F_NODNY) | (access & OPENACC_DWR) ? F_WRDNY : 0;
        shmd.f_id = ofrefnum;

        int fd = (eid == ADEID_DFORK) ? ad_data_fileno(adp) : ad_reso_fileno(adp);

        if (fd != -1 && fd != AD_SYMLINK && fcntl(fd, F_SHARE, &shmd) != 0) {
            LOG(log_debug, logtype_afpd, "fork_setmode: fcntl: %s", strerror(errno));
            errno = EACCES;
            return -1;
        }
    }
#endif

    if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
        return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_NONE, 1, ofrefnum);
    }

    if ((access & (OPENACC_RD | OPENACC_DRD))) {
        if ((readset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
            return readset;
        if ((denyreadset = ad_testlock(adp, eid, AD_FILELOCK_DENY_RD)) <0)
            return denyreadset;

        if ((access & OPENACC_RD) && denyreadset) {
            errno = EACCES;
            return -1;
        }
        if ((access & OPENACC_DRD) && readset) {
            errno = EACCES;
            return -1;
        }
        /* boolean logic is not enough, because getforkmode is not always telling the
         * true
         */
        if ((access & OPENACC_RD)) {
            ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_RD, 1, ofrefnum);
            if (ret)
                return ret;
        }
        if ((access & OPENACC_DRD)) {
            ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_RD, 1, ofrefnum);
            if (ret)
                return ret;
        }
    }
    /* ------------same for writing -------------- */
    if ((access & (OPENACC_WR | OPENACC_DWR))) {
        if ((writeset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
            return writeset;
        if ((denywriteset = ad_testlock(adp, eid, AD_FILELOCK_DENY_WR)) <0)
            return denywriteset;

        if ((access & OPENACC_WR) && denywriteset) {
            errno = EACCES;
            return -1;
        }
        if ((access & OPENACC_DWR) && writeset) {
            errno = EACCES;
            return -1;
        }
        if ((access & OPENACC_WR)) {
            ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_WR, 1, ofrefnum);
            if (ret)
                return ret;
        }
        if ((access & OPENACC_DWR)) {
            ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_WR, 1, ofrefnum);
            if (ret)
                return ret;
        }
    }

    return 0;
}